近日因工作关系,需要用STM8L101F3P6这款单片机用IO口模拟串行通讯,波特率2400bps,前辈同事已经写完了程序,我需要拿来研究一下该款MCU的低功耗的情况,而在调试的过程中,发现1个奇怪的问题,描述如下:
在while(1){}的循环中,无论是接收还是发送。第一次循环的收发数据都是错的,此后的循环均正确。比如:PC一个字符一个字符的发送0x01,0x02,0x03,接收到3个字符MCU就发回来,但第1次循环接收到是错误数据0x40,0xA0,0xE0,此后再循环收发均正确。。。百思不得其解,在while(1)循环内还会出这种问题?
代码如下:
/********************************************** 描述:用延时法模拟串口通讯,中断方式接收 硬件: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); } }
病症如下:
-----------------------------------------------------------------------------------------------------------------------------------
上电后:
此时已经能看出问题了,想想看。
-----------------------------------------------------------------------------------------------------------------------------------
发送0x01:
-----------------------------------------------------------------------------------------------------------------------------------
发送0x02:
-----------------------------------------------------------------------------------------------------------------------------------
发送0x03:
-----------------------------------------------------------------------------------------------------------------------------------
症状:
-----------------------------------------------------------------------------------------------------------------------------------
再发0x01:
-----------------------------------------------------------------------------------------------------------------------------------
再发0x02:
-----------------------------------------------------------------------------------------------------------------------------------
再发0x03:
看到这,我想应该知道问题出现在哪了吧?哈哈。
-----------------------------------------------------------------------------------------------------------------------------------
分析:
用IO口模拟串行通讯,串口通讯的起始位用低电平0表示,停止位用高电平1来表示。在没有进行数据收发的时候,要使TXD保持高电平,以便能识别出特发数据的起始位。解决办法是,上电初始化时,使TXD引脚为高电平。
-----------------------------------------------------------------------------------------------------------------------------------
病好了: