共计 1747 个字符,预计需要花费 5 分钟才能阅读完成。
从 Larduino_HSP 取得的 LGT8F328P 的 bootloader 通过串口与主机通信, 其波特率为 57600bps. 修改更新的波特率可以提高写入速度, 节省时间. 如果直接在 Makefile 修改为 115200bps 的话
BAUD_RATE_CMD = -DBAUD_RATE=115200
编译会有波特率偏移超过 2% 的提示, 可能会影响通信.
警告:#warning BAUD_RATE error greater than -2% [-Wcpp]
这里主要修改两个地方, 以更好的工作在 115200bps.
1. 启用倍速功能
倍速工作模式
通过设定 UCSRA 寄存器的 U2X 位可以是传输速率加倍,该位只在异步工作模式下有效,同
步工作模式下置该位为“0”。
设置该位将会把波特率分频器的分频值减半,有效地加倍异步通信的传输速率。在这种情况
下,接收器只使用一半的采样数来对数据进行采样及时钟恢复,因此需要更精准的波特率设
置和系统时钟。发送器则没有变化。
参考手册, 启用倍速功能, 此时波特率计算公式为
工作模式 | 波特率计算公式 | UBRR 值计算公式 |
---|---|---|
异步倍速模式 | $${\rm BAUD} = \frac{\large f_{\rm sys}}{\quad 8({\rm UBRR}+1)\quad }$$ | $${\rm UBRR} = \frac{\large f_{\rm sys}}{\quad 8{\rm BAUD}\quad } – 1$$ |
当系统时钟为 16000000, 波特率取115200 时, 依公式
$${\rm UBRR} = \displaystyle \frac{16000000}{8*115200} – 1 \approx 16.36$$
UBRR 将被赋值为0x10. 此时实际的波特率约为
$${\rm BAUD} = \displaystyle \frac{16000000}{\quad 8(16+1)\quad }\approx 117647$$
偏差
$$\frac{115200-117647}{115200}\approx -2.1\%$$
在 optiboot.c 中修改代码:
int main(void) {
...
UART_SRA = _BV(U2X0); //Double speed mode USART0
UART_SRL = (uint8_t)(F_CPU / (BAUD_RATE * 8L) - 1 );
...
}
2. 调整系统时钟频率
内部 RC 振荡器校准
LGT8FX8P 内部包含两个可校准 RC 振荡器,经过校准后,均可达到±1% 以内的精度。其
中 32MHz RC 默认用于系统工作时钟。
LGT8FX8P 出产前,内部 32MHz HFRC 和 32KHz LFRC 都进行了校准,并把校准值写入系
统配置信息区域。系统上电过程中,这些校准值将会被读入到内部寄存器中,通过寄存器实
现对 RC 频率的重新校准。
bootloader 的系统时钟源使用的是内部 32MHz HFRC, 并通过设置 32MHz HFRC 振荡器校准寄存器 - RCMCAL, 达到±1% 以内的精度. 为使串口通信速率更接近 115200bps, 这时我们通过调整系统时钟来调整波特率.
依前面公式, 输出标准 115200bps 时, 系统时钟最佳值为:
$$\large f_{\rm sys} = {\rm BAUD}*{8({\rm UBRR}+1)}=115200*8(16+1)=15667200$$
通过修改寄存器 CLKPR 的CKOEN0位, 在 PB0 上检测系统时钟频率. 以下为实测的经验数据:
RCMCAL 调整值 | 系统时钟频率 | 与理想偏差 |
---|---|---|
0 | 16026400 | 2.293% |
-1 | 15962200 | 1.883% |
-2 | 15896300 | 1.462% |
-3 | 15830000 | 1.039% |
-4 | 15765400 | 0.627% |
-5 | 15700700 | 0.214% |
-6 | 15636600 | -0.195% |
-7 | 15573500 | -0.598% |
-8 | 15510400 | -1.001% |
通过以上表格,RCMCAL 调整值为 - 5 或 - 6 时最接近理想值.
在 optiboot.c 中添加代码:
#if BAUD_RATE==115200
const uint8_t CAL_V=6;
if((uint8_t)RCMCAL>=CAL_V)
{RCMCAL -= CAL_V;}
else
{RCMCAL = 0;}
#endif
完整修改在 https://github.com/nicechao/Larduino_HSP 上查看