suncat0504 发表于 2022-5-12 22:13

【APM32E103xE测评】+SPI接口测试感悟及发现的串口问题

本帖最后由 suncat0504 于 2022-7-4 20:20 编辑

#申请原创# @21小跑堂
之前测试连接SPI接口的液晶屏的时候,使用的是GPIO口模拟方式实现的。今天着手测试APM32E103的SPI设备。首先使用例程来测试SPI口的通讯,熟悉相关代码。例程中使用SPI作为从设备,由串口1发数据给SPI,同时SPI发数据给串口。从而实现串口和SPI之间的双祥通讯。打开工程、编译、下载,程序运行都正常。然后开始挂载SPI液晶屏,依旧使用其它GPIO口模拟的方式驱动。在程序中加入液晶屏的初始化、测试,经过测试也都正常。然后把显示代码加到串口1与SPI的相互通讯中,显示通讯数据。代码如下:int main(void)
{
    int no=0;
    /** Buffer Compare state */
    uint8_t state = FALSE;
    /** SPI receive Buf*/
    uint8_t rxDataBufSPI   = {0x00};
    /** USART receive Buf*/
    uint8_t rxDataBufUSART = {0x00};
   
    // LCD液晶初始化
    lcd_25696_init();
   
    // 测试液晶
    lcd25696_test();
   
    Delay(0x3000);
   
    clear_screen();
   
    APM_MINI_LEDInit(LED2);
    APM_MINI_LEDInit(LED3);
    APM_MINI_LEDOff(LED2);
    APM_MINI_LEDOff(LED3);

    USART_FullDuplex_Init();
    SPI_FullDuplex_Init();
   
    display_string_16x16_textmode(0, 0, (uint8_t *)"init usart2:");
   
    // 初始化串口2
//#ifdef USART2_FullDuplex
//    USART2_FullDuplex_Init();
//#else
    usart2_init();
//#endif
   
    display_string_16x16_textmode(12, 0, (uint8_t *)"end");   
   
    Delay(0x5000);
    //clear_screen();
   
    display_string_16x16(0, 2, (uint8_t *)"COM发送:");
    display_string_16x16(0, 4, (uint8_t *)"SPI接收:");
    display_string_16x16(0, 6, (uint8_t *)"Spi发送:");
    display_string_16x16(0, 8, (uint8_t *)"COM接收:");
    for (int i = 0; i < DATA_BUF_SIZE; i++){
      no=i+48;
      // 串口发送数据,因为串口1有问题,根据设置,选择串口1或者串口2
      #ifdef USART2_FullDuplex
            USART_TxData(USART2, no);
      #else
            USART_TxData(USART1, no);
      #endif
      display_alpha_char(i*16+80, 2, hexchar);
      display_alpha_char(i*16+88, 2, hexchar);

      
      // SPI发送数据
      SPI_WriteByte(no);
      display_alpha_char(i*16+80, 6, hexchar);
      display_alpha_char(i*16+88, 6, hexchar);

      
      // SPI收到数据
      while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
      rxDataBufSPI = SPI_I2S_RxData(SPI1);
      display_alpha_char(i*16+80, 4, hexchar/16]);
      display_alpha_char(i*16+88, 4, hexchar%16]);
      
      // 等待串口收到来自SPI发出的数据
      #ifdef USART2_FullDuplex
            /* Wait data is received by UART1 */
            while (USART_ReadStatusFlag(USART2, USART_FLAG_RXBNE) == RESET);
            rxDataBufUSART = USART_RxData(USART2);
      #else
            /* Wait data is received by UART1 */
            while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
            rxDataBufUSART = USART_RxData(USART1);
      #endif
      display_alpha_char(i*16+80, 8, hexchar/16]);
      display_alpha_char(i*16+88, 8, hexchar%16]);
    }

    /** Compare receive Buffer*/
    state = BufferCompare(rxDataBufUSART, rxDataBufSPI, DATA_BUF_SIZE);

    /* Data is ok then turn on LED2 */
    if (state == 1)
    {
      APM_MINI_LEDOn(LED2);
    } else {
      APM_MINI_LEDOn(LED3);
    }

    while (1)
    {
      //APM_MINI_LEDToggle(LED3);
      Delay(0x7ffff);
    }
}下载运行,结果运行中的显示为:COM接收到的数据的第一个字节竟然是0x00,而不是臆想中的0x30。调整部分代码的执行顺序,依旧如此。暂时没有解决,到了做饭点,去做饭。吃完晚饭后,坐下来想了想,例程中的测试是正常的,我的代码仅仅是增加一些显示测试数据的代码。再想到SPI通讯的特点,想起来是同时双向传递数据的,使用同一个CLK完成,而在我的代码中,在收发处理之间加入了很多处理代码,是不是这部分代码导致了通讯数据有延时,导致错位?马上调整代码为如下形式:int main(void)
{
    int no=0;
    /** Buffer Compare state */
    uint8_t state = FALSE;
    /** SPI receive Buf*/
    uint8_t rxDataBufSPI   = {0x00};
    /** USART receive Buf*/
    uint8_t rxDataBufUSART = {0x00};
   
    // LCD液晶初始化
    lcd_25696_init();
   
    // 测试液晶
    lcd25696_test();
   
    Delay(0x3000);
   
    clear_screen();
   
    APM_MINI_LEDInit(LED2);
    APM_MINI_LEDInit(LED3);
    APM_MINI_LEDOff(LED2);
    APM_MINI_LEDOff(LED3);

    USART_FullDuplex_Init();
    SPI_FullDuplex_Init();
   
    display_string_16x16_textmode(0, 0, (uint8_t *)"init usart2:");
   
    // 初始化串口2
    usart2_init();
    display_string_16x16_textmode(12, 0, (uint8_t *)"end");   
   
    Delay(0x5000);
    //clear_screen();
   
    display_string_16x16(0, 2, (uint8_t *)"COM发送:");
    display_string_16x16(0, 4, (uint8_t *)"SPI接收:");
    display_string_16x16(0, 6, (uint8_t *)"Spi发送:");
    display_string_16x16(0, 8, (uint8_t *)"COM接收:");
    for (int i = 0; i < DATA_BUF_SIZE; i++){
      no=i+48;
      // 串口发送数据,因为串口1有问题,根据设置,选择串口1或者串口2
      USART_TxData(USART1, no);
      // SPI发送数据
      SPI_WriteByte(no);
      
      display_alpha_char(i*16+80, 2, hexchar);
      display_alpha_char(i*16+88, 2, hexchar);
      display_alpha_char(i*16+80, 6, hexchar);
      display_alpha_char(i*16+88, 6, hexchar);
      
      // SPI收到数据
      while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
      rxDataBufSPI = SPI_I2S_RxData(SPI1);
      
      // 等待串口收到来自SPI发出的数据
      /* Wait data is received by UART1 */
      while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
      rxDataBufUSART = USART_RxData(USART1);
    }
   
    for (int i = 0; i < DATA_BUF_SIZE; i++){
      display_alpha_char(i*16+80, 4, hexchar/16]);
      display_alpha_char(i*16+88, 4, hexchar%16]);
      display_alpha_char(i*16+80, 8, hexchar/16]);
      display_alpha_char(i*16+88, 8, hexchar%16]);
    }

    /** Compare receive Buffer*/
    state = BufferCompare(rxDataBufUSART, rxDataBufSPI, DATA_BUF_SIZE);

    /* Data is ok then turn on LED2 */
    if (state == 1)
    {
      APM_MINI_LEDOn(LED2);
    } else {
      APM_MINI_LEDOn(LED3);
    }

    while (1)
    {
      //APM_MINI_LEDToggle(LED3);
      Delay(0x7ffff);
    }
}编译、下载、运行。液晶显示为:终于正常了。这次的测试,给了自己一个教训。单片机执行速度很快,是微秒级的,在自己看来,这些都很短,在处理液晶显示的时候,花的时间可以忽略不计。然而在时序要求比较严格的地方,就可能造成无法预知的后果。这个情况,就像在有些I2C通讯的时候,如果出现了别的中断处理导致I2C通讯的延迟,等中断结束的时候,I2C通讯已经不能被正常执行了,是一样的道理。而且,自己也忽视了SPI双向通讯的特点,所出现这个结果太正常了。希望自己能牢牢记住这次的教训,避免下次再犯同样的错误。在测试中,我还发现另外一个不解的问题,就是在下载了和串口有关的代码后(如这次的SPI测试),串口会在复位执行新下载的程序前,不断地向串口发出数据,以0x00居多,但没有规律。即使按下复位按钮不松开,发送也不会停止。在自己的印象中,执行复位,处于复位状态的微处理器是不应该工作的啊?怎么会发送串口数据呢?我的这个程序中的串口1和串口2都用了,但和串口2比,串口1使用了USART1_CK(PA8)这个信号,结果在复位状态下串口1不断发出数据,但串口2却没有。为了验证,把串口2也按照串口1方式初始化,使用USART2_CK(PA4),然后观察复位状态下串口2是否也不断发出数据。结果串口2也出现了不断发数据的情况。这个问题,我估计自己是解决不了了,只好告知极海的技术人员了。希望能解决。

WoodData 发表于 2022-5-30 22:18

学习一下

mollylawrence 发表于 2022-9-7 16:30

可以测评oled吧

htmlme 发表于 2022-9-7 17:39

这个屏幕如何自定义字符嗯

wangdezhi 发表于 2022-9-7 18:52

这个测评很给力

sanxingnote7 发表于 2022-9-7 21:36

自带的spi吗

海滨消消 发表于 2022-9-13 16:26

非常不错给力的测评贴

xiaoyaodz 发表于 2022-10-5 17:31

串口存在什么问题呢?            

nomomy 发表于 2022-10-5 17:56

这个是硬件spi驱动的吗            

tifmill 发表于 2022-10-5 19:40

能不能使用spi驱动ws2812led灯呢

typeof 发表于 2022-10-9 21:13

spi的最大的驱动速度是多少hz

mattlincoln 发表于 2023-2-4 21:27

这个串口有什么问题?            

youtome 发表于 2023-2-4 21:37

如果是持续发送0的话,可能有干扰的。

kmzuaz 发表于 2023-2-5 13:30

用的最多的就是模拟spi,可移植性非常高。

janewood 发表于 2023-2-6 13:38

这个串口还有什么问题?            

hearstnorman323 发表于 2023-2-7 22:07

硬件spi的操作有bug吗?            

wilhelmina2 发表于 2023-2-8 17:49

串口的代码是怎么配置的?            

tifmill 发表于 2023-3-4 21:05

spi的最大通信的速度是多少            

olivem55arlowe 发表于 2023-3-7 21:28

spi的最大通信的速度是多少            

caigang13 发表于 2023-3-7 21:39

还是这种屏看起来眼睛舒服
页: [1]
查看完整版本: 【APM32E103xE测评】+SPI接口测试感悟及发现的串口问题