暑假有个小课题要做,今天是接手的第二天。这两天在做的时候遇到了一些问题,在这里就把这些记录下来,作为自己的特殊的财富。若是可以给遇到同样问题的人,一些帮助,那我会非常高兴。
以下就是自己一开始出错的地方,有些问题很简单,但不注意或者以前没有接触过就容易死磕在那。
(1)在使用STM32串口通信的时候,有个奇怪的现象:发送的第一个字节会丢失。我的代码一开始是这样的:
void uart1_send(u8 *pbuffer)
{
while((*pbuffer))
{
USART1->DR = *pbuffer++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == 0);//等待发送完毕,若发送完成则硬件置1
}
}
仔细看手册的时候发现 TC 和 TXE 标志位在复位的时候被置1 ,这样第一次while循环就是没有用的。这样导致了首次第一个字符还没有被输出,就被后面的字符覆盖掉,造成实际看到的丢失现象。解决方法如下:
void uart1_send(u8 *pbuffer)
{
USART_GetFlagStatus(USART1, USART_FLAG_TC);
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
上面这条语句解决第1个字节无法正确发送出去的问题 */
while((*pbuffer))
{
USART1->DR = *pbuffer++;
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == 0);//等待发送完毕,若发送完成则硬件置1
}
}
(2)课题项目中用到了一个激光测距传感器,它输出的格式是RS232。当时我不知道怎么回事,就直接把传感器的TX和RX引脚直接接到stm32的RX和TX。结果可想而知,调试很久,就是有问题。突然缓过神来,单片机输出的电平是TTL电平,他们电平不匹配。后来加了个MAX232,一切OK。
(3)说到这个MAX232,还吓出了一身冷汗。因为MAX232是5V器件,我把它直接连在了STM32的串口引脚了,瞎猫碰上死耗子,那两个引脚是5V容忍的。下次果断使用MAX3232。
(4)还是说说那个激光传感器,使用串口给那个传感器发送指令后,传感器会从串口返回数据。而我开启了串口接收中断,但要命的是我没写串口接收中断处理函数。然后发现程序死掉了。我的测试程序是写了条发送指令,然后在这条发送指令下面是点亮一个灯,发现灯一直不亮。因为接收到了数据,程序要跑到接收中断函数处,它找不到这个入口点,死掉了,所以执行不到点灯的那条指令。
(5)程序中一段ASC码转10进制的代码:
void a2i(void)
{
u8 i,k;
u16 temp=0;
for(k=1;k<row-2;k++)//激光传感器连续测量时第一组数据是错误的。
{ //所以从k=1开始
for(i=0;i<4;i++)
{
if(userdata.recbuf[k][i]!=0)
{
temp=(temp<<3)+(temp<<1); //乘以10
temp+=userdata.recbuf[k][i]&0x0F;
}
}
userdata.recnum[k]=temp;
temp=0;
}
}
这段程序的前提是我的那个传感器输出数据的格式是这样的比如508 mm。而5、0、8这几个数据都是以十六进制的ASC码发送回来的。巧的是比如:整形变量4的ASC码是34。正好是后面那个4。所以有程序中的这句:userdata.recbuf[k][i]&0x0F;
(6)typedef union
{
unsigned char recbuf[60][4];
int recnum[60];
}
USERDATA;
USERDATA xdata userdata;
这个用到了联合体,以前写程序的时候自己没怎么用,这里正好学习一下。
联合体的空间要大到足够容纳最"宽"的成员;所有成员引用的是内存中的相同位置。当你想在不同的时刻把不同的东西存储在同一个位置时,就可以使用联合。
上面这个代码可以减少数组声明占用的内存,不然int recnum[60]; 又要占用另外的内存了。
以上就是这两天的所学所得,有些东西可能在大神面前不值一提,有些东西可能说的不怎么对。若有不对的地方,请各位大神指点。