feat: spi demo with max7219 led matrix

This commit is contained in:
IOsetting 2022-01-01 23:58:02 +08:00
parent bfdf8f1213
commit 5c24252306
3 changed files with 144 additions and 9 deletions

114
demo/spi/max7219_8x8_led.c Normal file
View File

@ -0,0 +1,114 @@
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* Demo: MAX7219 8x8 LED Matrix
*
* P1.3 -> DIN
* P1.5 -> SCLK
* P1.7 -> CS
*/
#include "fw_hal.h"
#define MAX7219_CS P17
#define DECODE_MODE 0x09
#define INTENSITY 0x0A
#define SCAN_LIMIT 0x0B
#define SHUT_DOWN 0x0C
#define DISPLAY_TEST 0x0F
const uint8_t numbers[]={
0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xD6,0xD6, // -0-.
0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18, // -1-
0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30, // -2-
0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06, // -3-
0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE, // -4-
0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x0E, // -5-
0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6, // -6-
0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18, // -7-
0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6, // -8-
0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06, // -9-
0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00};
void MAX7219_write(uint8_t addr, uint8_t dat)
{
MAX7219_CS = 0;
SPI_TxRx(addr);
SPI_TxRx(dat);
MAX7219_CS = 1;
}
void MAX7219_init(void)
{
MAX7219_write(SHUT_DOWN, 0x01); // 0x00:shutdown, 0x01:normal
MAX7219_write(DECODE_MODE, 0x00); // Bypass code B decoder, no-decode operation
MAX7219_write(SCAN_LIMIT, 0x07); // Scan-limit, 0:1-digit, 1:2-digits, ... 7:8-digits
MAX7219_write(INTENSITY, 0x01); // 0x00:min, 0xFF:max
MAX7219_write(DISPLAY_TEST, 0x00); // 0x00:normal, 0x01:test mode
}
void SPI_init(void)
{
// MAX7219 can work with frequency up to 20MHz
SPI_SetClockPrescaler(SPI_ClockPreScaler_4);
// Clock idles low
SPI_SetClockPolarity(HAL_State_OFF);
// Data transfer is driven by lower SS pin
SPI_SetClockPhase(SPI_ClockPhase_LeadingEdge);
// MSB first
SPI_SetDataOrder(SPI_DataOrder_MSB);
// Define the output pins
SPI_SetPort(SPI_AlterPort_P12P54_P13_P14_P15);
// Ignore SS pin, use MSTR to swith between master/slave mode
SPI_IgnoreSlaveSelect(HAL_State_ON);
// Master mode
SPI_SetMasterMode(HAL_State_ON);
// Start SPI
SPI_SetEnableState(HAL_State_ON);
}
void main()
{
uint8_t pos = 0, size = sizeof(numbers), i, j;
SYS_SetClock();
// Configure GPIO pins before SPI and device
GPIO_P1_SetMode(GPIO_Pin_3, GPIO_Mode_InOut_QBD);
GPIO_P1_SetMode(GPIO_Pin_5|GPIO_Pin_7, GPIO_Mode_Output_PP);
// Configure SPI and device
SPI_init();
MAX7219_init();
while(1)
{
for (i = 0; i < 8; i++)
{
j = (pos + i) % size;
MAX7219_write(i + 1, numbers[j]);
}
pos = (pos + 1) % size;
SYS_Delay(100);
}
}

View File

@ -35,8 +35,9 @@ typedef enum
// SS MOSI MISO SCLK // SS MOSI MISO SCLK
SPI_AlterPort_P12P54_P13_P14_P15 = 0x00, SPI_AlterPort_P12P54_P13_P14_P15 = 0x00,
SPI_AlterPort_P22_P23_P24_P25 = 0x01, SPI_AlterPort_P22_P23_P24_P25 = 0x01,
SPI_AlterPort_P54_P40_P41_P43 = 0x10, SPI_AlterPort_P54_P40_P41_P43 = 0x02,
SPI_AlterPort_P35_P34_P33_P32 = 0x11, SPI_AlterPort_P35_P34_P33_P32 = 0x03,
SPI_AlterPort_8G1K08_8Pin = 0x00,
} SPI_AlterPort_t; } SPI_AlterPort_t;
typedef enum typedef enum
@ -47,6 +48,18 @@ typedef enum
SPI_ClockPreScaler_32or2 = 0x03, SPI_ClockPreScaler_32or2 = 0x03,
} SPI_ClockPreScaler_t; } SPI_ClockPreScaler_t;
typedef enum
{
SPI_ClockPhase_LeadingEdge = 0x00, // Bits are sampled on the leading edge of SCLK
SPI_ClockPhase_TrailingEdge = 0x01, // Bits are sampled on the trailing edge of SCLK
} SPI_ClockPhase_t;
typedef enum
{
SPI_DataOrder_MSB = 0x00, // High bits first
SPI_DataOrder_LSB = 0x01, // Low bits first
} SPI_DataOrder_t;
#define SPI_RxTxFinished() (SPSTAT & 0x80) #define SPI_RxTxFinished() (SPSTAT & 0x80)
#define SPI_ClearInterrupt() SFR_SET(SPSTAT, 7) #define SPI_ClearInterrupt() SFR_SET(SPSTAT, 7)
#define SPI_ClearWriteConflictInterrupt() SFR_SET(SPSTAT, 6) #define SPI_ClearWriteConflictInterrupt() SFR_SET(SPSTAT, 6)
@ -54,18 +67,27 @@ typedef enum
#define SPI_IgnoreSlaveSelect(__STATE__) SFR_ASSIGN(SPCTL, 7, __STATE__) #define SPI_IgnoreSlaveSelect(__STATE__) SFR_ASSIGN(SPCTL, 7, __STATE__)
#define SPI_SetEnableState(__STATE__) SFR_ASSIGN(SPCTL, 6, __STATE__) #define SPI_SetEnableState(__STATE__) SFR_ASSIGN(SPCTL, 6, __STATE__)
#define SPI_SetDataOrderLSB(__STATE__) SFR_ASSIGN(SPCTL, 5, __STATE__) #define SPI_SetDataOrder(__ORDER__) SFR_ASSIGN(SPCTL, 5, __ORDER__)
#define SPI_SetMasterMode(__STATE__) SFR_ASSIGN(SPCTL, 4, __STATE__) #define SPI_SetMasterMode(__STATE__) SFR_ASSIGN(SPCTL, 4, __STATE__)
// CPOL, 0:idle low, 1:idl high //
#define SPI_SetClockPolarHigh(__STATE__) SFR_ASSIGN(SPCTL, 3, __STATE__) /**
// CPHA, 0:SS low drive, 1:SCLK front edge drive * Clock Polarity, CPOL
#define SPI_SetClockFrontEdgeDrive(__STATE__) SFR_ASSIGN(SPCTL, 2, __STATE__) * 0: clock line idles low
* 1: clock line idles high
*/
#define SPI_SetClockPolarity(__STATE__) SFR_ASSIGN(SPCTL, 3, __STATE__)
/**
* Clock Phase (CPHA)
* 0: bits are sampled on the leading clock edge
* 1: bits are sampled on the trailing clock edge
*/
#define SPI_SetClockPhase(__PHASE__) SFR_ASSIGN(SPCTL, 2, __PHASE__)
/** /**
* SPI Clock * SPI Clock
*/ */
#define SPI_SetClockPrescaler(__PRE_SCALER__) (SPCTL = SPCTL & ~0x03 | ((__PRE_SCALER__) << 0)) #define SPI_SetClockPrescaler(__PRE_SCALER__) (SPCTL = SPCTL & ~0x03 | ((__PRE_SCALER__) << 0))
/** /**
* Alternative port selection * Alternative ports
*/ */
#define SPI_SetPort(__ALTER_PORT__) (P_SW1 = P_SW1 & ~(0x03 << 2) | ((__ALTER_PORT__) << 2)) #define SPI_SetPort(__ALTER_PORT__) (P_SW1 = P_SW1 & ~(0x03 << 2) | ((__ALTER_PORT__) << 2))

View File

@ -19,7 +19,6 @@
uint8_t SPI_TxRx(uint8_t dat) uint8_t SPI_TxRx(uint8_t dat)
{ {
SPI_ClearInterrupts();
SPDAT = dat; SPDAT = dat;
while (!SPI_RxTxFinished()); while (!SPI_RxTxFinished());
SPI_ClearInterrupts(); SPI_ClearInterrupts();