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

2020-03-23来源: eefocus关键字: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引脚为高电平。

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

病好了:

关键字:STM8L101  单片机  IO口  模拟串口通讯 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic492345.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM8 普通IO配置模拟串口输出
下一篇:模拟串口--基于STM8普通IO口的模拟串口驱动程序

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM8L152C6T6通过IIC接口操作M24LR64的正确波形
1.观察一下,M24LR04中0x0000~0x001F地址中的数据,这是一条ISO15693协议的报文。2.3.第1个字节,设备选择码0xA64.第2个和第3个字节,地址0x0000。
发表于 2020-03-26
STM8L152C6T6通过IIC接口操作M24LR64的正确波形
STM8L101F3P6串口查询接收
; *//* Descriptions:         STM8L103F3P6,内部时钟,16MHz,串口查询接收,接收1个字 *//*                       符                                         
发表于 2020-03-26
STM8L101F3P6关于微秒级延时函数不同写法的波形
总结一下STM8L101F3P6工作在16MHz下,利用死循环、中断等不同写法的微秒级延时函数精度的情况。一、死循环空指令的写法,延时函数程序如下:/******************************************************************************//* Function name:       Delay_us                               
发表于 2020-03-26
STM8L101F3P6关于微秒级延时函数不同写法的波形
stm8s和stm8l低功耗对比
  在低功耗应用中,一般来说mcu是常态halt模式,然后偶尔被唤醒(外部中断或者内部定时唤醒)进入运行模式。所以对比低功耗性能,一般来说只需要对比run模式和halt下的功耗即可,因为项目选用的是通过内部定时器唤醒,所以选用active halt mode。以下是stm8s003和stm8l151在这两种模式下的功耗对比: run mode: stm8s    stm8l  对比   在使用同样的16M内部RC振荡器情况下,stm8s 3.7ma,stm8l 3.54ma,两款mcu耗电量差不多。active halt mode:stm8s   stm8l   
发表于 2020-03-25
stm8s和stm8l低功耗对比
提升安全防御能力,STM32L5超低功耗MCU贸泽开售
专注于引入新品并提供海量库存的电子元器件分销商贸泽电子 (Mouser Electronics) 即日起开始备货STMicroelectronics (ST) 的STM32L5超低功耗微控制器。STM32L5系列采用集成Arm TrustZone® 硬件安全技术的Arm® Cortex®-M33内核,并具有一组保护功能和嵌入式高速存储器,性能高,功耗低。       贸泽电子备货的STM32L5微控制器采用以Arm TrustZone为基础并支持ARMv8-M主要扩展选项的安全架构。此32位Cortex-M33内核具有浮点运算单元、一组DSP(数字信号处理)指令,以及用于
发表于 2020-03-24
提升安全防御能力,STM32L5超低功耗MCU贸泽开售
9课:单片机数据传递类指令
单片机数据传递类指令(3)以直接地址为目的操作数的指令MOV direct,A 例: MOV 20H,AMOV direct,Rn MOV 20H,R1MOV direct1,direct2 MOV 20H,30HMOV direct,@Ri MOV 20H,@R1MOV direct,#data MOV 20H,#34H(4)以间接地址为目的操作数的指令MOV @Ri,A 例:MOV @R0,AMOV @Ri,direct MOV @R1,20HMOV @Ri,#data MOV @R0,#34H(5)十六位数的传递指令MOV DPTR,#data168051是一种8位机,这是唯一的一条16位立即
发表于 2020-03-10
9课:单片机数据传递类指令
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved