一次GPRS调试引出的大发现--STM32发送字符串第一个字符丢失

这几天一直再做gprs的调试工作,开始从网上得到的例程,在单片机上给GPRS发指令,单片机可以收到模块返回的指令。讲这次经历之前,先简单介绍下单片机如何给GPRS发AT指令的,AT指令有很多,在每发一个AT指令后都需要单片机给模块再发送一个回车“\r\n"字符才表示发送完成。下面是参考的发送指令部分:

for (; *b!='\0';b++)//*为发送的AT指令
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
USART_SendData(USART2,*b);//UART2_SendData(*b);
}

USART2_Puts("\r\n");//发送回车

然后我参考了例程的发送指令函数移植到自己的工程里,结果一个百思不得其解的现象出现了:自己的程序下到单片机,然后给GPRS发指令,却无法得到模块的反应。因为这个问题调试了整整一天,同样的发送指令函数,到了自己的程序里怎么就无法实现了?当时的内心几乎是崩溃的!!

其实,还是自己不够细心(之前一直以为发送指令函数没问题而一直忽略)。后面的不断调试和检查中,在程序中发现了一个非常重要的细节,自己写的发送回车字符的函UART2_SendLR();

 例程的该函数内容是:

void USART2_Puts(char * str)

  while(*str)
  {
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET); 
USART_SendData(USART2 ,*str++);//发送当前字符

  } 
}

而自己的函数是:

void USART2_Puts(char * str)

  while(*str)
  {
USART_SendData(USART2 ,*str++);//发送当前字符
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE)==RESET); 
  } 
}

两条语句的顺序和标志位不一样,之前一直用这函数都正常,所以没去在意,但和先前的发AT指令部分结合,问题非常明显了,用我的函数话,发送完AT指令,那么未进行标志位判断就立马发送回车字符,此情况是不允许的,这样后面的字符会把前面的一个覆盖了,也就是AT指令的最后一个字符会消失,导致了GPRS无法识别而无返回数据。

因此将自己的函数进行了修改,问题解决了。

下面就是该问题牵引出的一个发现。由于两函数判断标志位不一样,判断与发送的次序也不一样,因此出于好奇,想通过此函数发送字符串给上位机,看显示效果是否一样,

结果发现了一个奇怪现象:例程的函数发送的字符串,第一个字符总会在程序复位开始时会丢失。而当使用USART_FLAG_TXE来判断时,可以正常。

通过网上查找了这两标志位的区别,查到了单片机的串口发送接收机制

发送:软件将数据写到USARTx->DR里面,硬件自动把USARTx->DR里面的数据并行转移到“发送一位寄存器”,然后硬件自动将发送一位寄存器中的数据通过TX引脚串行发送出去。

接收:RX上有数据过来,则先将数据一位一位的放到“接收移位寄存器”里面,收满一个字节后,硬件自动将“接收移位寄存器”里面的数据并行转移到USARTx->DR里面。

while (!(USART1->SR & USART_FLAG_TC));这句是等待数据完完全全从“发送移位寄存器”中发送出去,while (!(USART1->SR & USART_FLAG_TXE));这句是等待数据从USARTx->DR转移到“发送移位寄存器”中。在后一句的写法中,并不需等待数据完全发送,只需要USARTx->DR里面的数据已经被转移走,就可以马上进行再次写入USARTx->DR操作,这样是不是就可以节省很多时间了?

至于出现乱码,你需要综合其他的代码来进行分析。(注:while (!(USART1->SR & USART_FLAG_TC));相于 while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET); while (!(USART1->SR & USART_FLAG_TXE));相当于while(USART_GetFlagStatus(USART2, USART_FLAG_TXE)==RESET); )

因此,USART_FLAG_TXE会先于USART_FLAG_TC判断,只要数据发送,USART_FLAG_TXE就会置0;而USART_FLAG_TC的判断会有所延迟,需要数据到了移位寄存器才能为0。这也就解释了为什么用USART_FLAG_TC会使得第一个数据无法判断,而丢失。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值