[APM32E1]

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

[复制链接]
1693|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的相互通讯中,显示通讯数据。代码如下:
int main(void)
{
    int no=0;
    /** Buffer Compare state */
    uint8_t state = FALSE;
    /** SPI receive Buf*/
    uint8_t rxDataBufSPI[DATA_BUF_SIZE]   = {0x00};
    /** USART receive Buf*/
    uint8_t rxDataBufUSART[DATA_BUF_SIZE] = {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[no/16]);
        display_alpha_char(i*16+88, 2, hexchar[no%16]);

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

        
        // SPI收到数据
        while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
        rxDataBufSPI[i] = SPI_I2S_RxData(SPI1);
        display_alpha_char(i*16+80, 4, hexchar[rxDataBufSPI[i]/16]);
        display_alpha_char(i*16+88, 4, hexchar[rxDataBufSPI[i]%16]);
        
        // 等待串口收到来自SPI发出的数据
        #ifdef USART2_FullDuplex
            /* Wait data is received by UART1 */
            while (USART_ReadStatusFlag(USART2, USART_FLAG_RXBNE) == RESET);
            rxDataBufUSART[i] = USART_RxData(USART2);
        #else
            /* Wait data is received by UART1 */
            while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
            rxDataBufUSART[i] = USART_RxData(USART1);
        #endif
        display_alpha_char(i*16+80, 8, hexchar[rxDataBufUSART[i]/16]);
        display_alpha_char(i*16+88, 8, hexchar[rxDataBufUSART[i]%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);
    }
}
下载运行,结果运行中的显示为:

2

2
COM接收到的数据的第一个字节竟然是0x00,而不是臆想中的0x30。调整部分代码的执行顺序,依旧如此。
暂时没有解决,到了做饭点,去做饭。吃完晚饭后,坐下来想了想,例程中的测试是正常的,我的代码仅仅是增加一些显示测试数据的代码。再想到SPI通讯的特点,想起来是同时双向传递数据的,使用同一个CLK完成,而在我的代码中,在收发处理之间加入了很多处理代码,是不是这部分代码导致了通讯数据有延时,导致错位?马上调整代码为如下形式:
int main(void)
{
    int no=0;
    /** Buffer Compare state */
    uint8_t state = FALSE;
    /** SPI receive Buf*/
    uint8_t rxDataBufSPI[DATA_BUF_SIZE]   = {0x00};
    /** USART receive Buf*/
    uint8_t rxDataBufUSART[DATA_BUF_SIZE] = {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[no/16]);
        display_alpha_char(i*16+88, 2, hexchar[no%16]);
        display_alpha_char(i*16+80, 6, hexchar[no/16]);
        display_alpha_char(i*16+88, 6, hexchar[no%16]);
        
        // SPI收到数据
        while (SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
        rxDataBufSPI[i] = SPI_I2S_RxData(SPI1);
        
        // 等待串口收到来自SPI发出的数据
        /* Wait data is received by UART1 */
        while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
        rxDataBufUSART[i] = USART_RxData(USART1);
    }
   
    for (int i = 0; i < DATA_BUF_SIZE; i++)  {
        display_alpha_char(i*16+80, 4, hexchar[rxDataBufSPI[i]/16]);
        display_alpha_char(i*16+88, 4, hexchar[rxDataBufSPI[i]%16]);
        display_alpha_char(i*16+80, 8, hexchar[rxDataBufUSART[i]/16]);
        display_alpha_char(i*16+88, 8, hexchar[rxDataBufUSART[i]%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);
    }
}
编译、下载、运行。液晶显示为:

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 | 显示全部楼层
这个屏幕如何自定义字符嗯

使用特权

评论回复
评论
suncat0504 2022-9-8 10:55 回复TA
因为不带字库,所以需要自己建立一个映射文件,组织点阵数据。 
wangdezhi| | 2022-9-7 18:52 | 显示全部楼层
这个测评很给力

使用特权

评论回复
sanxingnote7| | 2022-9-7 21:36 | 显示全部楼层
自带的spi吗

使用特权

评论回复
评论
suncat0504 2022-9-8 10:56 回复TA
是的 
海滨消消| | 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吗?              

使用特权

评论回复
评论
suncat0504 2023-2-8 08:56 回复TA
这个倒是没发现 
wilhelmina2| | 2023-2-8 17:49 | 显示全部楼层
串口的代码是怎么配置的?              

使用特权

评论回复
tifmill| | 2023-3-4 21:05 | 显示全部楼层
spi的最大通信的速度是多少              

使用特权

评论回复
评论
suncat0504 2023-3-5 09:03 回复TA
没测试过,得看用户手册 
olivem55arlowe| | 2023-3-7 21:28 | 显示全部楼层
spi的最大通信的速度是多少              

使用特权

评论回复
caigang13| | 2023-3-7 21:39 | 显示全部楼层
还是这种屏看起来眼睛舒服

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

85

主题

2400

帖子

4

粉丝