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

[复制链接]
3285|23
 楼主| suncat0504 发表于 2022-5-12 22:13 | 显示全部楼层 |阅读模式
本帖最后由 suncat0504 于 2022-7-4 20:20 编辑

#申请原创#

  之前测试连接SPI接口的液晶屏的时候,使用的是GPIO口模拟方式实现的。今天着手测试APM32E103SPI设备。首先使用例程来测试SPI口的通讯,熟悉相关代码。例程中使用SPI作为从设备,由串口1发数据给SPI,同时SPI发数据给串口。从而实现串口和SPI之间的双祥通讯。打开工程、编译、下载,程序运行都正常。然后开始挂载SPI液晶屏,依旧使用其它GPIO口模拟的方式驱动。在程序中加入液晶屏的初始化、测试,经过测试也都正常。

1

1
然后把显示代码加到串口1SPI的相互通讯中,显示通讯数据。代码如下:
  1. int main(void)
  2. {
  3.     int no=0;
  4.     /** Buffer Compare state */
  5.     uint8_t state = FALSE;
  6.     /** SPI receive Buf*/
  7.     uint8_t rxDataBufSPI[DATA_BUF_SIZE]   = {0x00};
  8.     /** USART receive Buf*/
  9.     uint8_t rxDataBufUSART[DATA_BUF_SIZE] = {0x00};
  10.    
  11.     // LCD液晶初始化
  12.     lcd_25696_init();
  13.    
  14.     // 测试液晶
  15.     lcd25696_test();
  16.    
  17.     Delay(0x3000);
  18.    
  19.     clear_screen();
  20.    
  21.     APM_MINI_LEDInit(LED2);
  22.     APM_MINI_LEDInit(LED3);
  23.     APM_MINI_LEDOff(LED2);
  24.     APM_MINI_LEDOff(LED3);

  25.     USART_FullDuplex_Init();
  26.     SPI_FullDuplex_Init();
  27.    
  28.     display_string_16x16_textmode(0, 0, (uint8_t *)"init usart2:");
  29.    
  30.     // 初始化串口2
  31. //#ifdef USART2_FullDuplex
  32. //    USART2_FullDuplex_Init();
  33. //#else
  34.     usart2_init();
  35. //#endif
  36.    
  37.     display_string_16x16_textmode(12, 0, (uint8_t *)"end");   
  38.    
  39.     Delay(0x5000);
  40.     //clear_screen();
  41.    
  42.     display_string_16x16(0, 2, (uint8_t *)"COM发送:");
  43.     display_string_16x16(0, 4, (uint8_t *)"SPI接收:");
  44.     display_string_16x16(0, 6, (uint8_t *)"Spi发送:");
  45.     display_string_16x16(0, 8, (uint8_t *)"COM接收:");
  46.     for (int i = 0; i < DATA_BUF_SIZE; i++)  {
  47.         no=i+48;
  48.         // 串口发送数据,因为串口1有问题,根据设置,选择串口1或者串口2
  49.         #ifdef USART2_FullDuplex
  50.             USART_TxData(USART2, no);
  51.         #else
  52.             USART_TxData(USART1, no);
  53.         #endif
  54.         display_alpha_char(i*16+80, 2, hexchar[no/16]);
  55.         display_alpha_char(i*16+88, 2, hexchar[no%16]);

  56.         
  57.         // SPI发送数据
  58.         SPI_WriteByte(no);
  59.         display_alpha_char(i*16+80, 6, hexchar[no/16]);
  60.         display_alpha_char(i*16+88, 6, hexchar[no%16]);

  61.         
  62.         // SPI收到数据
  63.         while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
  64.         rxDataBufSPI[i] = SPI_I2S_RxData(SPI1);
  65.         display_alpha_char(i*16+80, 4, hexchar[rxDataBufSPI[i]/16]);
  66.         display_alpha_char(i*16+88, 4, hexchar[rxDataBufSPI[i]%16]);
  67.         
  68.         // 等待串口收到来自SPI发出的数据
  69.         #ifdef USART2_FullDuplex
  70.             /* Wait data is received by UART1 */
  71.             while (USART_ReadStatusFlag(USART2, USART_FLAG_RXBNE) == RESET);
  72.             rxDataBufUSART[i] = USART_RxData(USART2);
  73.         #else
  74.             /* Wait data is received by UART1 */
  75.             while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
  76.             rxDataBufUSART[i] = USART_RxData(USART1);
  77.         #endif
  78.         display_alpha_char(i*16+80, 8, hexchar[rxDataBufUSART[i]/16]);
  79.         display_alpha_char(i*16+88, 8, hexchar[rxDataBufUSART[i]%16]);  
  80.     }

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

  83.     /* Data is ok then turn on LED2 */
  84.     if (state == 1)
  85.     {
  86.         APM_MINI_LEDOn(LED2);
  87.     } else {
  88.         APM_MINI_LEDOn(LED3);
  89.     }

  90.     while (1)
  91.     {
  92.         //APM_MINI_LEDToggle(LED3);
  93.         Delay(0x7ffff);
  94.     }
  95. }
下载运行,结果运行中的显示为:

2

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

  25.     USART_FullDuplex_Init();
  26.     SPI_FullDuplex_Init();
  27.    
  28.     display_string_16x16_textmode(0, 0, (uint8_t *)"init usart2:");
  29.    
  30.     // 初始化串口2
  31.     usart2_init();
  32.     display_string_16x16_textmode(12, 0, (uint8_t *)"end");   
  33.    
  34.     Delay(0x5000);
  35.     //clear_screen();
  36.    
  37.     display_string_16x16(0, 2, (uint8_t *)"COM发送:");
  38.     display_string_16x16(0, 4, (uint8_t *)"SPI接收:");
  39.     display_string_16x16(0, 6, (uint8_t *)"Spi发送:");
  40.     display_string_16x16(0, 8, (uint8_t *)"COM接收:");
  41.     for (int i = 0; i < DATA_BUF_SIZE; i++)  {
  42.         no=i+48;
  43.         // 串口发送数据,因为串口1有问题,根据设置,选择串口1或者串口2
  44.         USART_TxData(USART1, no);
  45.         // SPI发送数据
  46.         SPI_WriteByte(no);
  47.         
  48.         display_alpha_char(i*16+80, 2, hexchar[no/16]);
  49.         display_alpha_char(i*16+88, 2, hexchar[no%16]);
  50.         display_alpha_char(i*16+80, 6, hexchar[no/16]);
  51.         display_alpha_char(i*16+88, 6, hexchar[no%16]);
  52.         
  53.         // SPI收到数据
  54.         while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
  55.         rxDataBufSPI[i] = SPI_I2S_RxData(SPI1);
  56.         
  57.         // 等待串口收到来自SPI发出的数据
  58.         /* Wait data is received by UART1 */
  59.         while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
  60.         rxDataBufUSART[i] = USART_RxData(USART1);
  61.     }
  62.    
  63.     for (int i = 0; i < DATA_BUF_SIZE; i++)  {
  64.         display_alpha_char(i*16+80, 4, hexchar[rxDataBufSPI[i]/16]);
  65.         display_alpha_char(i*16+88, 4, hexchar[rxDataBufSPI[i]%16]);
  66.         display_alpha_char(i*16+80, 8, hexchar[rxDataBufUSART[i]/16]);
  67.         display_alpha_char(i*16+88, 8, hexchar[rxDataBufUSART[i]%16]);  
  68.     }

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

  71.     /* Data is ok then turn on LED2 */
  72.     if (state == 1)
  73.     {
  74.         APM_MINI_LEDOn(LED2);
  75.     } else {
  76.         APM_MINI_LEDOn(LED3);
  77.     }

  78.     while (1)
  79.     {
  80.         //APM_MINI_LEDToggle(LED3);
  81.         Delay(0x7ffff);
  82.     }
  83. }
编译、下载、运行。液晶显示为:

3

3
终于正常了。
  这次的测试,给了自己一个教训。单片机执行速度很快,是微秒级的,在自己看来,这些都很短,在处理液晶显示的时候,花的时间可以忽略不计。然而在时序要求比较严格的地方,就可能造成无法预知的后果。这个情况,就像在有些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 | 显示全部楼层
这个屏幕如何自定义字符嗯

评论

因为不带字库,所以需要自己建立一个映射文件,组织点阵数据。  发表于 2022-9-8 10:55
wangdezhi 发表于 2022-9-7 18:52 | 显示全部楼层
这个测评很给力
sanxingnote7 发表于 2022-9-7 21:36 | 显示全部楼层
自带的spi吗

评论

是的  发表于 2022-9-8 10:56
海滨消消 发表于 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吗?              

评论

这个倒是没发现  发表于 2023-2-8 08:56
wilhelmina2 发表于 2023-2-8 17:49 | 显示全部楼层
串口的代码是怎么配置的?              
tifmill 发表于 2023-3-4 21:05 | 显示全部楼层
spi的最大通信的速度是多少              

评论

没测试过,得看用户手册  发表于 2023-3-5 09:03
olivem55arlowe 发表于 2023-3-7 21:28 | 显示全部楼层
spi的最大通信的速度是多少              
caigang13 发表于 2023-3-7 21:39 来自手机 | 显示全部楼层
还是这种屏看起来眼睛舒服
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:大连伊飞特信息技术有限公司软件工程师
简介:本人于1993年毕业于大连理工大学。毕业后从事单片机开发工作5年,之后转入软件开发工作至今。

158

主题

4507

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部