打印
[STM8]

【转】分析解决“STM8L101单片机IO口模拟串口通讯发生的奇...

[复制链接]
959|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
南国先生|  楼主 | 2016-11-2 23:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

近日因工作关系,需要用STM8L101F3P6这款单片机用IO口模拟串行通讯,波特率2400bps,前辈同事已经写完了程序,我需要拿来研究一下该款MCU的低功耗的情况,而在调试的过程中,发现1个奇怪的问题,描述如下:

在while(1){}的循环中,无论是接收还是发送。第一次循环的收发数据都是错的,此后的循环均正确。比如:PC一个字符一个字符的发送0x01,0x02,0x03,接收到3个字符MCU就发回来,但第1次循环接收到是错误数据0x40,0xA0,0xE0,此后再循环收发均正确。。。百思不得其解,在while(1)循环内还会出这种问题?

代码如下:

[cpp] view plain copy


  • /**********************************************
  • 描述:用延时法模拟串口通讯,中断方式接收
  • 硬件:2MHz,内部默认16Mhz,8分频,STM8L101F3P6,RXD---PB7.TXD---PB4
  • 波特率:2400
  • 测试:上电后,分别发送0x01,0x02,0x03,3个字符。
  • 问题:第1次循环接收到的字符不正确,但第2次以后均正确
  • 时间:2012.07.26 于单位
  • **********************************************/  
  • #include "stm8l10x.h"  
  • #include "stm8l10x_clk.h"  
  • #include "stm8l10x_gpio.h"  
  •   
  • #define RXD_IN  (GPIO_Pin_7)                    //RXD  
  • #define TXD_OUT (GPIO_Pin_4)                    //TXD  
  •   
  • unsigned char ReadBuf[64];                      //接收缓冲  
  •   
  • void CLK_Init(void)  
  • {  
  •     CLK_DeInit();  
  •     CLK_MasterPrescalerConfig(CLK_MasterPrescaler_HSIDiv8);  
  • }  
  •   
  • void IOInit(void)  
  • {     
  •     GPIO_Init(GPIOA, GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3, GPIO_Mode_Out_PP_Low_Slow );   
  •       
  •     GPIO_Init(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 , GPIO_Mode_Out_PP_Low_Slow );     
  •       
  •     //2012.07.26 添加  
  •     //造成问题的原因在于此,添加下面的语句可解决问题  
  •     //串行通讯的起始位为低电平,上电之后TXD,RXD都应置为高电平  
  •     //GPIO_Init(GPIOB, TXD_OUT, GPIO_Mode_Out_PP_High_Slow);  
  •       
  •     GPIO_Init(GPIOB, RXD_IN, GPIO_Mode_In_PU_IT);     
  •   
  •     GPIO_Init(GPIOC, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 , GPIO_Mode_Out_PP_Low_Slow );  
  •       
  •     GPIO_Init(GPIOD, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Slow );  
  • }  
  •   
  • void Delay_us(unsigned int nCount)   
  • {   
  •     for (; nCount != 0; nCount--);  
  • }  
  •   
  • void Delay(u16 nCount)  
  • {  
  •     while (nCount != 0)  
  •     {  
  •         nCount--;  
  •     }  
  • }  
  •   
  • void Delay_ms(void)  
  • {  
  •     int i=0;  
  •     for (i=0; i<397; i++);     
  • }  
  •   
  • void SEND_1(void)  
  • {  
  •     GPIOB->ODR |=0x10;  //PB4=1,TXD   
  • }  
  •   
  • void SEND_0(void)  
  • {  
  •     GPIOB->ODR &=0xEF;  //PB4=0,TXD  
  • }  
  •   
  • void WriteByte(unsigned char sdata)  
  • {  
  •     unsigned char i;  
  •     unsigned char value=0;  
  •   
  •     //发送起始位  
  •     SEND_0();  
  •     Delay_us(100);//45  
  •       
  •     //发送数据位  
  •     for(i=0;i<8;i++)  
  •     {  
  •         value=(sdata&0x01);      //先传低位  
  •         if(value)   
  •         {  
  •             SEND_1();  
  •         }  
  •         else {  
  •             SEND_0();  
  •         }   
  •         Delay_us(88);//40  
  •         sdata=sdata>>1;  
  •     }  
  •   
  •     //停止位  
  •     SEND_1();  
  •     Delay_us(100);  //50  
  • }  
  •   
  • unsigned char ReadByte(void)      
  • {  
  •     unsigned char i,value=0;  
  •   
  •     while(1)  
  •     {  
  •         if(!(GPIO_ReadInputData(GPIOB)&0x80))  
  •         {  
  •             //等过起始位  
  •             Delay_us(100);  
  •               
  •             //接收8位数据位  
  •             for(i=0;i<8;i++)  
  •             {  
  •                 value>>=1;      
  •                 if((GPIO_ReadInputData(GPIOB)&0x80))  
  •                 {  
  •                     value|=0x80;  
  •                 }  
  •                 Delay_us(90);  
  •             }  
  •               
  •             Delay_us(50);  
  •               
  •             return value;  
  •         }  
  •     }  
  • }  
  •   
  • unsigned char ReadAndWrite(unsigned char *RBuf)  
  • {  
  •     GPIO_Init(GPIOB, RXD_IN, GPIO_Mode_In_PU_No_IT); // RXD  
  •   
  •     RBuf[0]=ReadByte();  
  •     RBuf[1]=ReadByte();  
  •     RBuf[2]=ReadByte();   
  •   
  •     WriteByte(RBuf[0]);  
  •     WriteByte(RBuf[1]);  
  •     WriteByte(RBuf[2]);  
  •                      
  •     return 1;  
  • }  
  •   
  • void main(void)  
  • {  
  •     unsigned char ccc;  
  •   
  •     CLK_Init();  
  •     IOInit();  
  •   
  •     EXTI_SetPinSensitivity(EXTI_Pin_7, EXTI_Trigger_Rising_Falling);              
  •     enableInterrupts();   
  •   
  •     while(1)  
  •     {     
  •         ccc=ReadAndWrite(ReadBuf);  
  •     }     
  • }  


沙发
南国先生|  楼主 | 2016-11-2 23:29 | 只看该作者

病症如下:


-----------------------------------------------------------------------------------------------------------------------------------

上电后:

此时已经能看出问题了,想想看。

-----------------------------------------------------------------------------------------------------------------------------------

发送0x01:

-----------------------------------------------------------------------------------------------------------------------------------

发送0x02:

-----------------------------------------------------------------------------------------------------------------------------------

发送0x03:

-----------------------------------------------------------------------------------------------------------------------------------

症状:


-----------------------------------------------------------------------------------------------------------------------------------

再发0x01:

-----------------------------------------------------------------------------------------------------------------------------------

再发0x02:

-----------------------------------------------------------------------------------------------------------------------------------

再发0x03:

看到这,我想应该知道问题出现在哪了吧?哈哈。


使用特权

评论回复
板凳
南国先生|  楼主 | 2016-11-2 23:32 | 只看该作者

分析:

用IO口模拟串行通讯,串口通讯的起始位用低电平0表示,停止位用高电平1来表示。在没有进行数据收发的时候,要使TXD保持高电平,以便能识别出特发数据的起始位。解决办法是,上电初始化时,使TXD引脚为高电平。

-----------------------------------------------------------------------------------------------------------------------------------

病好了:


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

160

帖子

3

粉丝