以下以AVR单片机为例,使用内部RC振荡器8MHz系统时钟频率,上位机与单片机通讯出现问题:
首先分析原因:
1. 出于成本考虑没有使用外部晶振而是RC内部振荡器,精度较差,误差范围是标称值的±3%,而且系统振荡频率随温度的不同也会有一定的变化,因此根据标称的系统时钟频率来计算波特率就会产生相应的误差。
2. 当设置系统时钟为8MHz时,波特率一般都是习惯性的设置为9600、19200,115200等300的倍数,计算结果会有一定的误差。
例如波特率设置为9600,根据计算公式:
UBRRL=(FOSC/BAUD1/16-1)%256;
UBRRH=(FOSC/BAUD1/16-1)/256;
经计算得到的波特率寄存器初值UBRRH=0,UBRRL=51(实际值为51.083),就有一定的误差。用51反推波特率的数值为9615,误差率为0.16%,虽然不是很大,但是如果数据连续发送量较大则会有累计误差导致错码。
解决办法:
1. 能使用外部晶振当然是最好的解决办法。
2. 在使用内部RC振荡器的情况下:
1)使用官方给的方法对内部RC进行校准。
2)波特率的设置不一定要设置为9600等常用数值,而是针对8MHz计算能得到波特率寄存器数值为整数,这样就不存在取整导致的误差。
例如将波特率设置为10000,计算所得UBRRH=0,UBRRL=49,波特率寄存器的值刚好是整数,避免了取整误差。
上位机波特率也调整为10000,
3)避免一次发送大量数据,避免累计误差。
4)上位机可以用查询的方式来确定当前温度适用的波特率,例如可以设定9600±200Hz范围,每50Hz为一个步进给下位机发送一个多字节信号,并且发送多次,以是否每次都能收到下位机正常反馈信号为判断依据来决定当前的上位机波特率。
本人在使用方法2)和3)就使得问题有了明显改善。波特率调整到20000也能正常通讯,调整到50000失败。