From 5c24252306e4a186d6c967a661cbedd615f85656 Mon Sep 17 00:00:00 2001 From: IOsetting Date: Sat, 1 Jan 2022 23:58:02 +0800 Subject: [PATCH] feat: spi demo with max7219 led matrix --- demo/spi/max7219_8x8_led.c | 114 +++++++++++++++++++++++++++++++++++++ include/fw_spi.h | 38 ++++++++++--- src/fw_spi.c | 1 - 3 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 demo/spi/max7219_8x8_led.c diff --git a/demo/spi/max7219_8x8_led.c b/demo/spi/max7219_8x8_led.c new file mode 100644 index 0000000..0f80b2a --- /dev/null +++ b/demo/spi/max7219_8x8_led.c @@ -0,0 +1,114 @@ +// Copyright 2021 IOsetting +// +// 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); + } +} \ No newline at end of file diff --git a/include/fw_spi.h b/include/fw_spi.h index fb6b72d..0ad683b 100644 --- a/include/fw_spi.h +++ b/include/fw_spi.h @@ -35,8 +35,9 @@ typedef enum // SS MOSI MISO SCLK SPI_AlterPort_P12P54_P13_P14_P15 = 0x00, SPI_AlterPort_P22_P23_P24_P25 = 0x01, - SPI_AlterPort_P54_P40_P41_P43 = 0x10, - SPI_AlterPort_P35_P34_P33_P32 = 0x11, + SPI_AlterPort_P54_P40_P41_P43 = 0x02, + SPI_AlterPort_P35_P34_P33_P32 = 0x03, + SPI_AlterPort_8G1K08_8Pin = 0x00, } SPI_AlterPort_t; typedef enum @@ -47,6 +48,18 @@ typedef enum SPI_ClockPreScaler_32or2 = 0x03, } 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_ClearInterrupt() SFR_SET(SPSTAT, 7) #define SPI_ClearWriteConflictInterrupt() SFR_SET(SPSTAT, 6) @@ -54,18 +67,27 @@ typedef enum #define SPI_IgnoreSlaveSelect(__STATE__) SFR_ASSIGN(SPCTL, 7, __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__) -// 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 -#define SPI_SetClockFrontEdgeDrive(__STATE__) SFR_ASSIGN(SPCTL, 2, __STATE__) +// +/** + * Clock Polarity, CPOL + * 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 */ #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)) diff --git a/src/fw_spi.c b/src/fw_spi.c index 88ab700..71b9584 100644 --- a/src/fw_spi.c +++ b/src/fw_spi.c @@ -19,7 +19,6 @@ uint8_t SPI_TxRx(uint8_t dat) { - SPI_ClearInterrupts(); SPDAT = dat; while (!SPI_RxTxFinished()); SPI_ClearInterrupts();