一直對STM8S的硬件SPI感興趣,但沒有真正使用過,以往都是用IO口模擬,這次剛好有個板子上有兩個595驅動的8位LED數碼管,就在上面試了一把,把過程記錄一下。
硬件接線圖:
595是數據接收器件,所以MCU只用了3條線與之相連,分別是MOSI接SER,SCK接CLK,NSS接RCK。其實這里RCK可以用其他的IO口的。
相關的代碼:
LOCAL uint8 DISP_BUF[8]={0,1,2,3,4,5,6,7}; //顯示緩沖區
PUBLIC uint8 DISP_TAB[]= //顯示碼表
{
0x14,0xD7,0x4C,0x45,0x87,0x25,0x24,0x57,0x04,0x05,0x06,0xA4,0x3C
};
相關的IO口設為上拉輸出
LOCAL void gpio_init(void)
{
GPIO_DeInit(GPIOC);
GPIO_Init(GPIOC,GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_DeInit(GPIOE);
GPIO_Init(GPIOE,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_FAST);
}
SPI初始化
LOCAL void spi_init(void)
{
SPI_DeInit();
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, ENABLE);
SPI_Init(SPI_FIRSTBIT_LSB, SPI_BAUDRATEPRESCALER_256, SPI_MODE_MASTER, SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_1LINE_TX, SPI_NSS_SOFT, 0x07);
SPI_Cmd(ENABLE);
}
顯示程序
PUBLIC void DISP_Display(void)
{
uint8 i,dig = 0x80;
for (i=0;i<8;i++)
{
GPIO_WriteLow(GPIOE,GPIO_PIN_5);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
SPI_SendData(DISP_TAB[DISP_BUF[i]]);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
SPI_SendData(dig);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
delay(20);
dig >>= 1;
}
}
編譯運行,出現的字符如下:
用示波器看了下,MOSI腳和SCK腳的波形正常。猜想是硬件SPI的速度太快,595跟不上。于是修改代碼,在兩次發送數據之后都延時一下。
PUBLIC void DISP_Display(void)
{
uint8 i,dig = 0x80;
for (i=0;i<8;i++)
{
GPIO_WriteLow(GPIOE,GPIO_PIN_5);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
SPI_SendData(DISP_TAB[DISP_BUF[i]]);
delay(500);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
SPI_SendData(dig);
delay(500);
while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
delay(20);
dig >>= 1;
}
}
再次編譯運行,顯示如下:
結論:
1. STM8S 硬件SPI的速度較快,實際應用的時候需要考慮外部設備的響應速度問題。
2. while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);只能保證每次SPI發送數據前,發送緩沖區是空的,即上次數據已經發送完成,但不能保證外部設備正確接收了數據。