㈠ stc单片机容易跑飞
stc芯片本身不稳定,抗干扰能力极差!stc单片机不能用于工控。跑飞原因有几个
1 看看有没有堆栈溢出
2程序储存段有没有越界。
3电源电压不稳,加大电源滤波电容加一个5伏稳压二极管
4io口是否受到外界干扰最好加光耦隔离
5如果自动复位,复位引脚不用时接上拉电阻到5伏,同时引脚加个对地电容
6板子地线要接地
㈡ 单片机波
#include<reg52.h> //包含头文件
#include<intrins.h>
#define uchar unsigned char //宏定义
#define uint unsigned int
sbit s1=P3^5; //定义按键的接口
sbit s2=P3^6;
sbit s3=P3^7;
sbit s4=P3^4;
sbit s5=P2^3;
sbit led0=P3^0; //定义四个LED,分别表示不同的波形
sbit led1=P3^1;
sbit led2=P3^2;
sbit led3=P3^3;
sbit lcdrs=P2^7; //液晶控制引脚,还有一个控制脚是RW,因为我们只需要向液晶里写数据系那是就好了,所以,我们直接将RW引脚接地
sbit lcden=P2^6;
char num,boxing,u; //定义全局变量
uchar pinlv=100,bujin=1,bujin1=1; //频率初始值是10Hz,步进值默认是0.1,显示步进值变量
uchar code table[]="0123456789"; //定义显示的数组
uchar code table1[]="Fout= Wave form:"; //初始化显示字符
unsigned int m,pwm=50; //定义变量 m
int a,b,h,num1; //定义全局变量
//自定义字符
uchar code zifu[]={ //此数组内数据为液晶上显示波形符号的自定义字符
0x0e,0x11,0x11,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x11,0x11,0x0e,0x00, //正弦波 0 1
0x00,0x07,0x04,0x04,0x04,0x04,0x1c,0x00,
0x00,0x1c,0x04,0x04,0x04,0x04,0x07,0x00, //矩形波 2 3
0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00,
0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00, //三角波 4 5
0x00,0x01,0x03,0x05,0x09,0x11,0x00,0x00, //锯齿波 6
};
uchar code sin[64]={ //此数组内的数据为,da输出对应电压值对应的数字量,0是0V,255是5V
135,145,158,167,176,188,199,209,218,226,234,240,245,249,252,254,254,253,251,247,243,237,230,222,213,204,193,182,170,158,
146,133,121,108,96,84,72,61,50,41,32,24,17,11,7,3,1,0,0,2,5,9,14,20,28,36,45,55,66,78,90,102,114,128
}; //正弦波取码
uchar code juxing[64]={ //一个周期是采样64个点, 所以数组内是64个数据
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
}; //矩形波取码
uchar code sanjiao[64]={
0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,
248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,0
}; //三角波取码
uchar code juchi[64]={
0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,
146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255
}; //锯齿波取码
void delay(uint xms) //延时函数
{
int a,b;
for(a=xms;a>0;a--)
for(b=110;b>0;b--);
}
void write_com(uchar com) //写命令函数
{
lcdrs=0;
P0=com;
delay(1);
lcden=0;
delay(1);
lcden=1;
}
void write_date(uchar date) //写数据函数
{
lcdrs=0;
P0=date;
delay(1);
lcden=0;
delay(1);
lcden=1;
}
//自定义字符集
void Lcd_ram()
{
uint i,j,k=0,temp=0x04;
for(i=0;i<7;i++)
{
for(j=0;j<8;j++)
{
write_com(temp+j);
write_date(zifu[k]);
k++;
}
temp=temp+8;
}
}
void init_lcd() //初始化函数
{
uchar i;
lcden=0; //默认开始状态为关使能端,见时序图
Lcd_ram();
write_com(0x01); //显示清屏,将上次的内容清除,默认为0x01.
write_com(0x0f);
write_com(0x38); //显示模式设置,默认为0x38,不用变。
write_com(0x0c); //显示功能设置0x0f为开显示,显示光标,光标闪烁;0x0c为开显示,不显光标,光标不闪
write_com(0x06); //设置光标状态默认0x06,为读一个字符光标加1.
write_com(0x80); //设置初始化数据指针,是在读指令的操作里进行的
for(i=10;i<20;i++) //显示初始化
{
write_date(table1[i]); //显示第一行字符
}
write_com(0x80+40); //选择第二行
for(i=0;i<9;i++)
{
write_date(table1[i]); //显示第二行字符
}
write_com(0x80+10); //选择第一行第十个位置
write_date(0);
write_date(1);
write_date(0);
write_date(1);
write_date(0);
write_date(1); //显示自定义的波形图案
write_com(0x80+40+9); //选择第二行第九个位置
write_date(' ');
write_date('1');
write_date('0');
write_date('.');
write_date('0');
write_date('H');
write_date('z'); //显示初始的频率值
}
void initclock() //定时器初始化函数
{
TMOD=0x01; //定时器的工作方式
TH0=a;
TL0=b; //定时器赋初值
EA=1; //打开中断总开关
ET0=1; //打开定时器允许中断开关
TR0=1; //打开定时器定时开关
}
void display() //显示函数
{
uchar qian,,shi,ge; //定义变量用于显示
qian=pinlv/1000; //将频率值拆成一位的数据,将数据除以1000,得到的商是一位数,赋值给qian
=pinlv%1000/100; //将频率除以1000的余数再除以100就得到了频率的百位,赋值给
shi=pinlv%1000%100/10; //同上,得到频率的十位
ge=pinlv%1000/100%10;
write_com(0x80+40+9); //选中第二行第九个位置
if(qian==0) //千位如果为0
write_date(' '); //不显示
else //千位不为0
write_date(table[qian]); //正常显示千位
if(qian==0&&==0) //千位和百位都为0
write_date(' '); //百位不显示
else //不都为0
write_date(table[]); //百位正常显示
write_date(table[shi]); //显示十位数
write_date('.'); //显示小数点
write_date(table[ge]); //显示个位
write_date('H'); //显示频率的单位Hz
write_date('z');
if(boxing==0) //判断波形为正弦波
{
write_com(0x80+10); //选中一行频率图案位置
write_date(0); //显示正弦波图案
write_date(1);
write_date(0);
write_date(1);
write_date(0);
write_date(1);
led3=1;
led0=0; //点亮正弦波指示灯
}
if(boxing==1) //注释同上
{
write_com(0x80+10);
write_date(2);
write_date(3);
write_date(2);
write_date(3);
write_date(2);
write_date(3);
led0=1;
led1=0;
}
if(boxing==2)
{
write_com(0x80+10);
write_date(4);
write_date(5);
write_date(4);
write_date(5);
write_date(4);
write_date(5);
led1=1;
led2=0;
}
if(boxing==3)
{
write_com(0x80+10);
write_date(6);
write_date(6);
write_date(6);
write_date(6);
write_date(6);
write_date(6);
led2=1;
led3=0;
}
}
void keyscan() //频率调节键盘检测函数
{
if(s1==0) //加按键是否按下
{
EA=0; //关闭中断
while(!s1); //按键松开
pinlv+=bujin; //频率以步进值加
if(pinlv>1000) //最大加到100Hz
{
pinlv=100; //100Hz
}
display(); //显示函数
m=65536-(15000/pinlv);//计算频率
/*频率值最小是10Hz,pinlv的值是100(因为要显示小数点后一位),150000/100=1500,这个1500就是定时器需要计时的,单位是us,65536-1500得到的是定时器的初值,
先不管初值,先看定时时间,1500us,一个波形的周期是由64个定时组成的,所以,一个波形周期就是64*1500us=96000,也就是96ms,约等
于100ms,也就是10Hz的频率*/
a=m/256; //将定时器的初值赋值给变量
b=m%256;
EA=1; //打开中断总开关
}
if(s2==0) //减按键按下
{
EA=0;
while(!s2);
pinlv-=bujin; //频率以步进值减
if(pinlv<100)
{
pinlv=100;
}
display();
m=65536-(15000/pinlv);
a=m/256;
b=m%256;
EA=1;
}
if(s3==0) //波形切换按键
{
EA=0;
while(!s3);
boxing++; //波形切换
if(boxing>=4) //4种波形
{
boxing=0;
}
display();
EA=1;
}
if(s5==0) //PWM切换按键
{
EA=0;
while(!s5);
pwm+=10;
if(pwm>90)
{
pwm=10;
}
// display();
EA=1;
}
}
void bujindisplay() //步进值设置界面显示程序
{
uint ,shi,ge; //定义步进值 百十个位
=bujin1/100; //将步进值除以100得到百位,也就是频率值的十位,因为有一个小数位
shi=bujin1%100/10; //将步进值除以100的余数除以十得到十位
ge=bujin1%100%10; //取余10后得到个位,也就是频率步进值的小数点后一位
write_com(0x80+11); //选中液晶第一行第十一列
if(==0) //百位是否为0
write_date(' '); //百位不显示
else //百位不为0
write_date(table[]); //显示百位数据
write_date(table[shi]); //显示十位数据
write_date('.'); //显示小数点
write_date(table[ge]); //显示个位,也就是小数点后一位
}
void bujinjiance() //步进值设置键盘程序
{
if(s4==0) //步进设置按键按下
{
delay(5); //延时去抖
if(s4==0) //再次判断按键
{
while(!s4); //按键释放,按键松开才继续向下执行
h++; //变量加
if(h==1) //进入设置状态时
{
write_com(0x01); //清屏
write_com(0x80); //初始化显示步进设置界面
write_date('S');delay(1); //step value
write_date('t');delay(1);
write_date('e');delay(1);
write_date('p');delay(1);
write_date(' ');delay(1);
write_date('v');delay(1);
write_date('a');delay(1);
write_date('l');delay(1);
write_date('u');delay(1);
write_date('e');delay(1);
write_date(':');delay(1);
bujin1=bujin; //步进值赋值给临时变量
bujindisplay(); //显示步进值
}
if(h==2) //退出设置
{
h=0; //清零
bujin=bujin1; //设置好的临时步进值赋值给步进变量
init_lcd(); //初始化液晶显示
initclock(); //定时器初始化
display(); //调用显示程序
}
}
}
if(h==1) //设置步进值时
{
if(s1==0) //加按键按下
{
delay(5); //延时去抖
if(s1==0) //再次判断
{
while(!s1); //按键释放
bujin1++; //步进值加1
if(bujin1>=101) //步进值最大100,也就是10.0Hz
{
bujin1=1; //超过最大值就恢复到0.1Hz
}
bujindisplay(); //步进显示
}
}
if(s2==0) //减按键,注释同上
{
delay(5);
if(s2==0)
{
while(!s2);
bujin1--; //步进减
if(bujin1<=0)
{
bujin1=100;
}
bujindisplay();
}
}
}
}
void main() //主函数
{
init_lcd(); //调用初始化程序
m=65536-(15000/pinlv); //定时器初值
a=m/256;
b=m%256;
initclock(); //定时器初始化
led0=0; //点亮第一个波形指示灯
while(1) //进入while循环,括号内为1,一直成立,所以也叫死循环,程序不会跳出,一直在内执行
{
if(h==0) //正常模式不是步进调节
{
keyscan(); //扫描按键
// display();
}
bujinjiance(); //扫描步进调节程序
switch(boxing) //选择波形
{
case 0 : P1=sin[u]; break; //正弦波
case 1 : //矩形波
if(u<pwm*64/100)P1=255;
else
P1=0;
break;
case 2 : P1=sanjiao[u]; break; //三角波
case 3 : P1=juchi[u]; break; //锯齿波
}
}
}
void T0_time()interrupt 1 //定时器
{
TH0=a;
TL0=b;
u++; //变量加
if(u>=64) //一个周期采样64个点, 所以加到64就清零
u=0; //u清零
//根据不同的初值,定时器定时时间不同,达到不同频率的目的
}
㈢ 51单片机串口发送u32丢数量
热门频道
首页
博客
研修院
VIP
APP
问答
下载
社区
推荐频道
活动
招聘
专题
打开CSDN APP
Copyright © 1999-2020, CSDN.NET, All Rights Reserved
单片机
打开APP
C51单片机串口丢包的几种情况分析! 转载
2021-03-22 11:29:28
3点赞
嵌入式资讯精选
码龄败租5年
关注
今天来总结一下C51单片机串口驱动层丢包的几种情况.
---C51单片机串拦枯衫口收发数据的原理---
1、串口驱动模块组成
(1)串口数据收发器,串口收发数据时,底层执行实际收发动作的硬件单元;
(2) 串口相关寄存器,
SBUF:串口数据寄存器,当有数据收或发时,用来装载收或发的数据,实际底层是分开收和发两个不同寄存器的,用户(程序员)只用SBUF就可以了;
RI:串口接收中断标志,告诉CPU现在串口收到数据了
TI:串口发简腔送中断标志,告诉CPU现在串口有数据要发了;
TI和RI都是系统产生用户软件清零的。
(3)串口中断服务函数;串口收数据和发数据的中断是一个,收和发在同一个中断服务函数进行,在RI为1时把寄存器SBUF里的数据拷贝到用户缓存里,在TI为1 时,把用户要发的数据装载到SBUF里。
2、收数据过程
(1)对端串口发送器发了1byte数据
(2) 串口接收器收到1byte数据,存到SBUF寄存器,并把寄存器中RI位置1
(3)系统产生一个中断,CPU内核轮询发现RI为1是串口中断,从用户程序跳转至串口中断服务函数
(4)串口中断服务函数中,把SBUF寄存器中的这1byte数据拷贝至用户缓存
收数据过程是1byte产生一个中断,也就是说数据是1byte 1byte收的。
数据流向过程如下图:
3、发数据过程
(1)用户把TI置1
(2) 系统产生中断,内核轮询到TI为1,跳转至串口中断服务函数
(3) 用户把1byte要发的数据装载至SBUF
(4)硬件发送器发送数据,发送完成自动把TI置1
(5)系统产生中断,重复(2)~(4)
(6) 当用户不再往SBUF装数据时,发送数据过程结束
发数据也是1byte 1byte发,每1byte先产生中断再装载数据。
数据流向过程如下图:
---串口丢包总结---
说明下,这是无操作系统的单片机程序。
我 = 串口硬件收发器+串口软件中断服务函数+串口相关寄存器。
用户 = 应用程序
1、我的硬件收发器在收发数据,用户把系统总中断关了
先说收数据的情况,系统中断被用户关了,我的硬件部分还是能收数据的,我仍然会把RI置1,但是现在总中断关了,就不会产生中断了,不会去调起我的软件中断服务函数了,那这样就会造成我放到SBUF里的数据还没有传给用户,如果关中断期间,我又收到了新的1byte数据,我就会把新的数据放到SBUF里,覆盖了老的数据了。
这样老的那1byte数据就丢掉了。
举例:串口正在收数据时,用户要写一些掉电记忆的参数到Flash,操作Flash会关总中断,此时如果串口在收数据可能会丢包。
解决:关总中断之前判断一下串口是不是在忙,串口无数据收到连续累计一段时间才认为闲。
发数据的情况会不会有问题?如果我的硬件在发数据,用户把总中断关了,我发完这1byte数据仍然会把TI置1,但是此时不会产生中断,不会再进入我的软件中断服务函数继续发数据,等中断恢复了,CPU会马上进入我的中断服务函数,又会继续发数据,所以发数据过程关总中断不会造成发数据丢包。
2、有人在中断服务函数里待太久,耽误我的软件收数据
我的硬件收到了数据,我把他放到了SBUF里,同时也置起了RI标志位,但不巧,这时候CPU在另一个中断服务函数里在执行代码,更不巧,这个中断服务函数很长,有很多代码要执行,要很久很久!
这不就误事了吗,CPU还没从那个中断服务函数出来,我的硬件又收到了新的1byte数据,我又把他装到了SBUF里,置起了RI,老的那1byte数据还在SBUF,没传给用户缓存呢,新的把他覆盖掉了。
举例:某MCU LED驱动用调光模式(即可调亮度模式),由于其中断服务函数太长,造成串口收数据丢包
解决:设置串口中断优先级高于LED中断优先级,C51中高优先级中断可以抢断低优先级中断,这样串口就不会丢包了。
3、大量数据又收又发,我的软件部分不够聪明,忙不过来了
同时有数据在收和发,我也是能应付的,因为咱是全双工的啊,收数据和发数据可以同时进行,是不同的硬件单元;此时RI和TI都会被我置成1,系统会进去中断服务函数,但系统是不知道这次进去是TI还是RI事件的,只管其中一个为1就进去了。
我的软件中断服务函数进去一次可以把收和发的数据都处理了,出来后就不会再次进中断服务函数了,
如果程序员把我的软件写成进一次中断服务函数只处理RI或者TI一个事件,那就效率很低啊!数据很多时极有可能会丢包!
比如如果优先处理TI事件,下次再进来想处理RI了但此时TI事件又有了,RI事件就又没处理到了。
如果优先处理RI事件,收到的数据不会丢,但是下次进来RI事件又产生了,又要处理RI事件,想发的数据一直没机会发。
所以,串口中断服务函数里要能同时处理RI 和TI 中断事件,下图中的else if 应改成if。
又如果,串口中断服务函数里面太长,前一次还没处理完,新的中断又到了,就会自己耽误自己。
4、当前数据还没发完,用户又把新数据装到我的SBUF中
我的硬件在发数据,此时TI已经被用户程序清0了,
如果程序员逻辑不够清晰,马上又要发一包新数据,把TI置1 了,那么CPU会马上进入中断服务函数,中断服务函数马上会把新的1byte 数据装到我的SBUF里,我刚刚正在发的那1byte 数据还没发完就被新数据覆盖弄丢了。
解决:程序串口驱动层接口发数据前,先判断当前是否处于发送数据过程中,若正在发送过程中,不用再将TI置1.
5、 我们这里总中断关了,对方还发数据给我
总中断关了,对方给我发数据,我的硬件还是能收到数据的,我也会把RI置1,但是此时就不会产生中断,不会进入中断服务函数了,如果对方马上又给我发了新的1byte数据,用户这时还是没有把总中断打开,刚刚那1byte数据还在SBUF中会被新来的数据覆盖,用户没取走丢掉了。
解决:对方增加重发逻辑。
6、我硬件能力不够,收发速度跟不上
用户竟然选择了系统时钟才2M,我的波特率却被设置成了115200这么大,
此时我的波特率发生器产生的波特率已经不能达到115200了,数据还是能1byte 1byte的发出去,只是就是发出去的数据电平的长度可能不对了,
标准串口每1byte数据 = 1bit起始位+ 8bit数据位+奇偶校验位(1或1.5或2或无)+停止位(1bit),起始电平是低电平,无数据时是高电平。
波特率115200即115200 bit/s,波特率决定了电平0/1的长度,波特率确定了1bit电平的长度就确定了,波特率越大,长度越短。
如果电平长度不对了,对方串口接收器收到这一串电平后经过解析可能就不认为这是一包正确的数据来了,因此丢弃了(底层电路具体是怎么样不是很了解)。
1.外媒谈英伟达-Arm并购案~
2.这里聚焦了全球嵌入式技术风景~
3.航天器、导弹喜欢用单片机?
4.工程师的硬核单片机编程思想~
5.嵌入式开发需要架构设计吗?
6.【技术转管理必备】嵌入式产品的研发流程
免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。
文章知识点与官方知识档案匹配
Java技能树首页概览
87773 人正在系统学习中
打开CSDN,阅读体验更佳
串口丢包受什么影响_总结一下曾经在串口方面犯的错误_weixin_39772652的...
串口接收端丢包严重时,如果不是因为明显错误导致,一般都是由于数据传输速度快,主控处理不过来造成的,想办法降低传输速度: (1)波特率: 最直接的方法就是降低波特率,我做过一个小实验,用帧序号来判断丢包情况,当丢包时亮起一盏灯,波特率...
Qt串口QSerialPort丢包问题,QSerialPort和QTimer定时器中断冲突的解决...
1.利用QTimer进行图像显示,每隔一定时间刷新图像 2.另一个线程同步读取串口中IMU的数据 3.测量时间可知,读取串口的线程在QTimer中断时耗时会大幅增加 还有一个问题是QSerialPort丢包。Qt5加入了QSerialPort的串口类,但经常会丢包,例如:...
51系列单片机串口缓存
51系列单片机串口缓存,已测试的单片机包括AT89C55WD、NXP89C669、STC11F60XE; buffer具有互锁机制,完美解决串口中断丢失数据,缓存数据等问题
填一个STC15F单片机串口通信的坑
STC单片机串口通信填坑最近在做个串口通信的案子,双方约定通信波特率为115200,进行过程中,双方按照50Hz频率发送数据包,包长最大30byte,接收时,为了不掉数据,我使用了环形FIFO,数据在串口中断写入,主程序通过读取FIFO来提取数据,使用FIFO读取数据时,为了保证数据可靠性,不能同时写入,所以需要将串口中断暂时关闭语句内容大致如下:{ES=0;语句1,语句2,ES=1}语句1和语句...
继续访问
Qt串口处理数据丢包问题_少安的砖厂的博客_qt 串口数据...
1.将串口类的readyRead信号连接到自定义的readData函数 connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); 2.readData函数:数据包格式为2位开始位,这个函数中使用有限状态机方法实现开始位判断。
linux嵌入式串口通信丢包,IMX6 Linux系统下串口丢包错包问题研究_墨菲...
无硬件流控串口丢包发生时机点: 处理当前串口中断的CPU被其他中断抢占 IMX6系列CPU,默认的IRQ中断优先级,是中断号小的,优先级高,可以优先处理。所以,如果当串口的数据已经来临,FIFO接受到的数据,已经达到触发中断的阈值,此时应该是产生串口...
51单片机串口打印乱码的解决方法
我使用的是stc的89c52rc型号,晶振是12m。是因为买的最小系统就是这个频率。使用波特率位9600,将TL、TH都设置成0xfd后不管是英文还是中文的都是乱码。
QT串口与51单片机通信
QT串口与51单片机通信 qt与单片机的串口通信 qt与单片机的串口通信 qt与单片机的串口通信
STC51单片机串口下载软件
STC51单片机的高级版本烧录器,包含串口开发助手功能,可选择发送多字节数据
串口通信丢包分析
RS232/RS422/RS485 异步通信通常使用一个UART 来发送和接受数据,用UART 芯片来控制串口的传输。UART芯片内部有一个FIFO缓冲区,用于存储软件驱动程序的输入数据。 FIFO的大小为1、16、64或128个字节,具体取决于UART类型。 FIFO用于通过缓冲数据来提高两个串行端口之间的通信吞吐量。接收和发送FIFO是独立的。 数据流向 (RX) 外部的串口设备-------> UART芯片的FIFO,FIFO数据到达trigger level ,触发中断-...
继续访问
最新发布 对于串口接收数据有丢包如何处理
对于串口接收数据有丢包如何处理
继续访问
单片机串口中断函数中,如果在里面时间过长,后面来的数据会被自动丢弃吗?答案是会丢数。很多串口测试实例上位机发送成功,但是下位机接收失败
单片机串口中断函数中,如果在里面时间过长,后面来的数据会被自动丢弃吗 我来答 分享 举报 2个回答 #热议#夫妻之间该做到绝对坦诚吗? 网络网友b30480f 高粉答主 推荐于2017-09-18·繁杂信息太多,你要学会辨别 关注 不是自动丢弃,而是反复接收,导致后来的数据将先收到、未处理的数据给覆盖了。 例如对方发给你一串0x01、0x02、0x03,假如你中断函数太过磨叽,可能在将0x01从缓冲区中取出后、在处理的过程中又先后收到了0x02、0x03,那么0x03...
继续访问
STM32串口通讯数据丢失原因分析及解决办法
在进行串口通讯实验时,一时不仔细可能会发现通讯不正常,数据丢失的现象,包括丢失第一个字符,或只收到最后一个字符等等,本文接下来将就这类问题展开讨论。 首先是通过MCU向上位机发送数据: 若程序如下图所示, 直接发送数据,由于数据缓冲区(TDR)向移位寄存器发送数据是并行发送,时间较快,而从移位寄存器向外传输数据是串行输出,耗时较长,如此可能导致数据丢失多个,或只接收到最后一个,因为后面并行传输的快,还没等数据发送完成,下一个数据就覆盖住了上一个数据。如此,有两种解决办法;一,添加发送...
继续访问
C51单片机多机串口通信,带数据校验
C51单片机多机串口通信,带数据校验,我自己全部编写的好东西适合你们下载
stc51单片机串口接收多字节数据
stc51单片机串口接收多字节数据 简介 51单片机有2个定时器,一个做串口波特率,一个做数据截止帧延时检测,硬件平台测试使用的是stc8的单片机,但是可以往51移植 代码 #include "stc8.h" unsigned char flag=0; //定义标志位,用来判断接收了多少个字符 void UartInit(void) //[email protected] { SCON = 0x50; //8位数据,可变波特率 AUXR |= 0x40; //定时器1时钟为Fosc,即1T
继续访问
51单片机的串口参数
常用模式为模式1和模式3 1. 波特率可变 2. 起始位为1,停止位为1,数据位为8, 3. 模式3可以选择奇偶校验位 ====================================================================== 最近刚好有项目使用到51的串口,整理了一下资料,固先记下,留待后用 模式0: 常用扩展IO 模式1: 波
继续访问
51中断(数据丢失)
51中断在没有执行完的情况下,中断再次发生这时是不会响应第二次中断的。或者说中断使能置没有打开这是来的中断变不会响应。 其实这是一个很明显的问题,只是在写程序的时候,特别遇到多中断处理的程序时便会产生数据的丢失。而且又是很容易被忽略这么简单的问题。
继续访问
单片机串口调试丢包验证过程记录 已解决
单片机串口调试丢包验证过程记录 已解决
继续访问
串口方面犯的错误
串口方面犯的错误 项目虽然做得不算多,但是关于串口的程序倒是写了不少,可能是我太笨了吧,每次写,每次错,错得五花八门,应有尽有,很少能一次性顺顺当当地搞定,更好笑的是有些错误是犯了好几次的,每次找到这样的错误,我都想给自己一个耳光。就在几个小时前,我又犯了一个愚蠢的错误,痛定思痛,这次一定要总结起来,算是给自己敲个警钟吧。 程序逻辑错误 我通常在串口接收中断里进行协议的判断,用不同的状态量来记录接收的情况,当完整地接收到一帧数据时,主控部分就可以对数据进行操作了。 假设要接收的数据协议格式为
继续访问
记一次串口丢包问题排查
1.项目中需要stm32和JN5169做串口通信,经测试大概有千分之一的丢包率。 2.排查步骤: 2.1.去掉关中断的地方 2.2.提高串口中断优先级 2.3.确定非线路问题 2.4.剪除系统,用裸机跑 3.最终发现,是相同优先级的中断抢占了串口中断,导致丢包。 ...
继续访问
关于Qt5 SerialPort串口传输丢失数据问题。
什么是Qt5 serialPort? 虽然现在大多数的家用PC机上已经不提供RS232接口了。但是由于RS232串口操作简单、通讯可靠,在工业领域中仍然有大量的应用。Qt以前的版本中,没有提供官方的对RS232串口的支持,编写串口程序很不方便。现在好了,在 Qt5.1 中提供了QtSerialPort模块,方便编程人员快速的开发应用串口的应用程序。 Qt5 serialPort存在的问题。
继续访问
串行口数据缓冲寄存器 SBUF 之 初步了解
c52系列的SBUF 有两个缓冲器 写SBUF 的操作完成待发送数据的加载,读SBUF 的操作可获得已接收到的数据。 两个操作分别对应两个不同的寄存器,一个是只写寄存器,一个是只读寄存器 在所有的串行通信方式中,在写入SBUF信号的控制下,把数据装入相同的九尾移位寄存器,前面八位为数据字节,其最低位为移位寄存器的输出位。根据不同的工作方式会自动将1或TB8的值装入移位寄存器的第九位,并进行发送 串...
继续访问
串口丢包
单片机
嵌入式
写评论
评论
10
3
踩
分享
㈣ 怎样解决变频器对单片机干扰的问题
变频器干扰单片机的主要途径,就是线路干扰,根据干扰频段的不同,可以选择变频器输入滤波器、变频器进线电抗器、磁环等,另外,还需要做好变频器的接地;如果距离不是很远的话,建议把变频器输出端与电机之间的联线,换成铠装电缆;
绿波杰能希望能帮到您!
㈤ 单片机中mtouch、CCP、ECCP、AUSART、EUSART、FS-USB、ECAN、BOR、PBOR、PLVD、SR-Latch是什么意思求解
CCP:捕捉、比较、脉宽调制(PWM)。这个模块可配置为工作在输入捕捉、定时器比较或 PWM 输出方式下
ECCP模块实现为具有增强型 PWM 功能的标准 CCP 模块。这些功能包括 2 或4 路输出通道、用户可选极性、死区控制和自动关闭与重启。 PWM 的增强型模式,ECCP模块的捕捉、 比较和单输出PWM功能与标准 CCP模块的相同。
AUSART,可寻址的通用同步异步串行口。EUSART,增强型的通用同步异步串行口。增强型的增加了一些性能,如:波特率自动检测和校准,更宽的波特率设置范围,以及一些适应LIN总线系统的性能。具体请看数据手册
BOR(欠压复位)模块是基于内部参考电压电路的。BOR 模块的主要用途是在发生欠压条件时
产生器件复位。欠压条件通常由 AC 电源上的干扰信号(即由于不良的电源传输线路造成的 AC
周期波形丢失)或接入大负载时过电流造成电压下降产生的。
POR:上电复位
PBOR:可编程的掉电锁定复位。
PLVD :可编程低压检测模块执行中断驱动的电源电压检测功能。电压检测监视内部电源电压。
ECAN 增强型控制器局域网模块是一个串行接口,用于同其他 CAN 模块或单片机器件进行通信。