20120726-分析解决“STM8L101单片机IO口模拟串口通讯发生的奇怪现象”

近日因工作关系,需要用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引脚为高电平。

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

病好了:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值