产品简介:单片机MSP430FR5992,LF为外部32.768K,HF为外部12M,ACLK=LF,SMCLK=HF,MCLK=DCO(21M,由于程序运算量较大,不得已用到了21M)。LF和HF都没有接到地电容。产品上电后的波特率固定为9600,上电后可以通过命令修改为4800,9600,19200,38400.但是断电都不保存。
现象:个别时候产品上电后串口输出的数据在9600波特率下无法解析,经测试发现无法解析的原因是波特率不是9600了,实际波特率绝大多数都是4800,比实际小了一倍,偶尔会有其他值,有一次是1920,比9600小了5倍。但是断电重启后可以恢复为9600。
我自己的测试过程:
- 将寄存器UCA0BRW,UCA0CTLW0, CSCTL3的值通过串口输出,检查配置值是否被修改了。
结果:上电后波特率是4800时,UCA0BRW的值仍然是9600对应的值。UCA0CTLW0的值也表示的也是串口时钟源是SMCLK, CSCTL3的值也表示SMCLK的分频值为1,即时钟没有分频。这几个值和上电正常时候的值完全一致。
- 上电波特率是4800时,通过产品中修改波特率的命令修改波特率。在4800下发送设置9600波特率的命令后,实际波特率还是4800,发送设置4800波特率的命令后实际波特率变为了2400(程序中就没有配置波特率为2400的代码),发送设置38400波特率的命令后实际波特率是19200,也就是设置后的实际波特率比预期小一半。
- 产品上有一个闪烁周期为1s的led,用定时器做的,定时器的时钟源本来是32.768,将定时器的时钟源改为SMCLK,当产品上电后波特率为4800时,发现led的闪烁周期变为了2s。
- 当上电后波特率是4800时,用示波器测量HF的值,是12M。
- 将时钟的寄存器CSCTL1- CSCTL6全部用串口输出,上电正常和上电波特率为4800时的值无差别。
- 在程序中增加通过命令调用时钟初始化和串口初始化的测试程序,当上电后波特率为4800时,发送命令重新初始化时钟和串口,无任何变化。
- 当上电后波特率是4800时,通过命令执行PMMCTL0=PMMPW+PMMSWPOR;(意思是通过软件方式触发一个POR),波特率可以恢复为9600.
综合上述测试,我个人觉得是SMCLK的值被分频了,但是又不知道是在哪分的,通过观察分频寄存器显示又没分频,另外还出来了一个5分频的情况,就算是通过分频器实现的,分频倍数也没有5倍啊,都是2/4/8….。另外就算时钟设置或者串口设置被修改了,为什么重新调初始化函数不起作用。还有为什么一个软件POR可以将波特率恢复为9600,是否相当于重新上电了。
void clk_init(void)//时钟初始化
{
FRCTL0=0XA500+NWAITS0+NWAITS1+NWAITS2;
PJDIR=0x00;
PJOUT=0;
PJREN=0xFF;
PJSEL0=PJSEL04+PJSEL05+PJSEL06+PJSEL07; //低频晶振选择
PJDIR|=(BIT5+BIT7);
CSCTL0=0xA500;//password
CSCTL1=DCOFSEL0+DCOFSEL2+DCORSEL;
CSCTL2=0;
CSCTL2=SELS0+SELS2+SELM0+SELM1;//ACK=LFXT 01=MCLK=DCOCLK
CSCTL3=0;//DIVM0;//ACK SMCLK SMCLK分频数为1
CSCTL4=VLOOFF+LFXTDRIVE0+LFXTDRIVE1+HFXTDRIVE0+HFXTDRIVE1+HFFREQ1;//关闭VLO
CSCTL5=0;
CSCTL6=ACLKREQEN+MCLKREQEN+SMCLKREQEN+MODCLKREQEN;//
do
{
PM5CTL0 &= ~LOCKLPM5;
CSCTL0=0xA500;//password
CSCTL0_H=0xa5;
CSCTL5 &= ~(LFXTOFFG+HFXTOFFG);
SFRIFG1&=~OFIFG;
delay(0xfff);
}
while(SFRIFG1&OFIFG);
}
补充一下,这个产品已经生产几百套了,目前就在一个板子上发现了这个问题。复现的频率不高,上电几十次到几百次大概能出现一次。
请各路高手指点一下会是什么原因造成的,困惑了好几天了,谢谢大家!