lvben5d 发表于 2019-8-16 09:42

裸跑GD32F芯片自我常犯的软件错误集锦和对策!

本帖最后由 lvben5d 于 2019-8-17 12:01 编辑

1.前几日发的定时器帖子,有关初始化里,用库函数初始化分频系数,周期的 xxxx_init函数内,存在软件更新事件的代码,如果你不清除标志位,直接使能定时器中断,那么就会先进中断一次。导致有个别定时功能意外的激发。
2.最近做LED点阵屏扫码程序时,发现对于08接口的单色屏扫16行大概,1ms就要扫1行,我把扫屏串行数据函数放在1ms定时器中断里,就会发现这个定时器会占用特别多CPU时间,我的串口中断即便在19200波特率下,总是会丢失字节(发生字节超时错误),原因在于定时器优先级高,且定时器内做的事情差不多需要0.5ms,我将串口中断优先级提升到可以抢占定时器中断,才不会发生串口字节丢失。虽然我主频已经是跑36MHZ了,串口中断接收1个字节,应该在1us内就可以中断处理完毕。
void TIMER14_IRQHandler(void)
{
      timer_disable(TIMER14);
      timer_interrupt_flag_clear(TIMER14, TIMER_INT_UP);
      timer_counter_value_config(TIMER14, 0);
      show_256x16_oneline(Sysinfo.scan_line);
      if(16 == ++Sysinfo.scan_line)   Sysinfo.scan_line = 0; //从第1行 扫到16行 再回到1行 舟而复始 索引0 是因为数组存储
      timer_enable(TIMER14);
}
3.keil5.2x采用新一代complier 6编译器,可以快速提升编译速度,但对于代码优化会跟c5不同,从而导致运行跟预先不符合。   void delay_us(unsigned char ctr)
{
    unsigned char nb;
   volatile unsigned char nop=1;
    for(; ctr>0; ctr--)
    {   
                for(nb=0; nb<US_UPPER; nb++)   //#elifdefined(RISC_36MHZ)    #defineUS_UPPER5
                nop++;
    }
}
c6编译器 如果不对nop进行io修饰,全速运行下,这个for循环会比你想的快很多(不能通过指令执行时间*估算一共需要执行多少次来==软延迟效果),而c5编译下,即便不用volatile 修饰,运行的效果 软延时时间会接近你 每条指令时间*大致的指令数。
4. 我相信大家用的较多的应用往往包含USART,在大部分应用中,确保串口中断的优先级,在中断方式接收数据的时候,一定要快速读取接收到字节。否则容易出现字节超时错误OV,从代码健壮性和易于恢复来说,你的接收中断子程序里还是要对这个进行处理(判断标志位 清接收标志 读下接收寄存器)。一定要开1个定时器做字节超时保护,用于串口数据包异常下的自我恢复能力。

hu9jj 发表于 2019-8-16 17:39

谢谢楼主分享,学习了。

kxsi 发表于 2019-9-9 14:57

非常感谢楼主分享

nawu 发表于 2019-9-9 15:17

很好的总结贴

qcliu 发表于 2019-9-9 15:45

非常不错的资料

luobo007 发表于 2021-3-24 17:42

最近在做GD32CAN总线功能,怎么都不好使,有没有经验传授一下

chenyelong 发表于 2021-5-5 23:29

luobo007 发表于 2021-3-24 17:42
最近在做GD32CAN总线功能,怎么都不好使,有没有经验传授一下

can通信解决了吗
页: [1]
查看完整版本: 裸跑GD32F芯片自我常犯的软件错误集锦和对策!