在c51单片机串口通讯时的问题,mpi send char_char什么意思,temp为什么要对256取整,取余。temp时无符号整型。

C51单片机串口通信_百度知道
C51单片机串口通信
我想使用89S52单片机做一个控制LED灯的实验,要求为:PC通过串口工具发送指令控制单片机,让其点亮或熄灭LED即可;
我尝试过发单字节是可以实现的,比如发 00给单片机,LED灯亮,发FF,LED灯灭;
我现在的问题是:比如我要发送多个字节来控制LED灯就不行了,...
我有更好的答案
可以通过缓冲区或者switch语句来实现 字符命令的话一般要buff区缓冲数据最后一次处理这样的只要switch语句就可以解决了。在串口中断加入如下代码:void UARTInterrupt(void) interrupt 4//串口中断{
stati//接收计数
//临时变量
switch(cont)
case 0:if(SBUF==0x1b){cont=1;}//检测第一个起始码
case 1:temp=SBUF-'0';temp=1&&cont=2;//获取要点亮的LED号
case 2:if(SBUF-1)P1&=~(temp);else P1|=cont=0;//判断点亮还是熄灭
你好,我按你上面说的把代码加上去了,但是好像没有看到有效果喔?请帮忙指正,谢谢!
#include &reg51.h&void InitUART(void){
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = TH1;
PCON = 0x00;
TR1 = 1;}void input(unsigned char str){stati//接收计数
stati//临时变量
switch(cont)
case 0:if(str==0x1b)//检测第一个起始码{cont=1;}
case 1:temp=str-0x30;//获取要点亮的LED号temp=cont&&cont=2;
case 2:if(str-1)//判断点亮还是熄灭P1|=else //P1口输出指定数据P1&=~cont=0;
}}void main(void){
InitUART();while(1);}void UARTInterrupt(void) interrupt 4//串口中断{
RI = 0;input(SBUF);
采纳率:70%
串口助手因为没有握手信号的关系,所以发送数据是没有等待的,因此,单片机端接受需要开辟缓冲区才可以保证数据不丢失。用C的话就,你就用一个数组来做就OK了。#include&reg51.h&#define uchar unsigned charuchar getdat[16],getp,sbit LED=P1^0;void serisr() interrupt 4{if(RI)
getdat[putp]=SBUF;
putp&=0x0f;
uchar comd[5],i;
TMOD=0x20;
SCON=0x50;
getp=putp=0;
if(getp!=putp)
comd[i]=getdat[getp];
getp&=0x0f;
if((comd[0]==0x1b))&&(comd[1]==0x31)&&(comd[2]==0x01))LED=0;
if((comd[0]==0x1b))&&(comd[1]==0x30)&&(comd[2]==0x02))LED=1;
你好,我试了把你上面的代码下载到芯片里面测试,但好像LED灯不能受PC的控制喔,请帮忙指正,谢谢!
#include&reg51.h&#define uchar unsigned charuchar getdat[16],getp,sbit LED=P1^0;void serisr() interrupt 4{if(RI)
getdat[putp]=SBUF;
putp&=0x0f;
uchar comd[5],i;
TMOD=0x20;
SCON=0x50;
getp=putp=0;
if(getp!=putp)
if((getdat[getp]==0x1b)||(i&0))
comd[i]=getdat[getp];
getp&=0x0f;
if((comd[0]==0x1b))&&(comd[1]==0x31)&&(comd[2]==0x01))LED=0;
if((comd[0]==0x1b))&&(comd[1]==0x30)&&(comd[2]==0x02))LED=1;
你这个是这样的,你检测两个和检测三个的长度改了吗? 我的意思是,如果你检测00两位的数组长度没有变, 那么你发三次就会变成01.
另外一种可能是,串口发送的时候,空格是不计的。电脑发送的,你程序里面判定要有空格了。
发你判定接受数据代码上来
不是很简单吗?在接收中断里面加个计数器,接收完3个字节数据后再对数据进行处理。
串口通讯和单片机控制LED灯是两回事,通讯的内容的含义自己可以随便定义,但必须编程实现协议的解释。
如果每隔一段时间led亮灭一次的话,比如亮一秒灭一秒吧,你可以定时1秒,送个高电平给口线,然后再定时1秒,把高电平取反给口线,如此循环就行了。
其他3条回答
为您推荐:
其他类似问题
串口通信的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。51单片机串口通信的学习笔记 - 单片机/MCU论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
51单片机串口通信的学习笔记
助理工程师
12:43:23  
23219&查看
呵呵,先来一个程序(摘自书上的,实现的是在上位机(pc机)上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机I get X串口波特率设为9600bps。代码如下:)#include &reg52.h&& && &&&
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,a,i;
uchar code table[]=&I get &;
/*--------初始化操作---------------*/
void init()& &&&
& & TMOD=0x20;& &&&//T1定时器工作方式2
& & TH1=0xfd;& && & //装初值
& & TL1=0xfd;& && & //装初值
& & TR1=1;& && && &//启动定时器1& && && && && && && &
//***********************************& &
& & SM0=0;& && &&&//设定串口工作方式1
& & SM1=1;& && && & //同上
& & REN=1;& && && & //允许串口接收& &
//***********************************& &
& & EA=1;& && && &//开总中断& &
& & ES=1;& && && &&&//开串口中断
& && && && && && & //因为定时器2是自动重装初值的因此不需要开定时器中断
/*---------------------------------*/
/*-------------主函数--------------*/
void main()
& & init();
& & while(1)
& && &&&if(flag==1)
& && && && &ES=0;
& && && && &for(i=0;i&6;i++)& && && &//发送数据
& && && && &{
& && && && && & SBUF=table[i];
& && && && && & while(!TI);
& && && && && & TI=0;
& && && && &}
& && && && &SBUF=a;
& && && && &while(!TI);
& && && && &TI=0;
& && && && &ES=1;
& && && && &flag=0;
/*-----------------------------------*/
/*--------------串口中断---------------*/
void ser() interrupt 4
& & a=SBUF;
& & flag=1;
/*------------------------------------*/
主程序的工作过程:当我们用串口调试助手发数据给单片机时,发送完后单片机接收到数据后会触发接收中断然后程序就会进入到接收中断中进行必要的处理,RI由软件清零为下一次中断做准备,然后把SBUF寄存器(接收到的)数据给变量a,最后置flag=1.然后回到主程序中检测到flag=1,再将前面定义的字符I get和串口发送的字符发送给pc机。while(!TI);是等待是否发送完毕的作用,当发送完毕后触发发送串口中断这时TI会自动置1,假设这时候已经发送完了我们就把TI由1置为0,再开串口中断,flag置零。又进行下一次了接收了。。。溢出率的计算单片机有四种串口方式,方式0和方式2的波特率是固定的,而方式1和3的波特率是可变的,具体设置多少由定时器T1的溢出率决定,溢出的频率越高波特率也越高,通信的速度也就越快。当然还与别的因素有关,具体波特率的计算有专门的公式。方式1的波特率计算公式(2^SMOD/32)x(T1溢出率)而方式0的波特率为fosc/12是固定的其中 fosc是单片机的晶振频率,通常为12MHZ和11.0592MHZ,公式中的SMOD是PCON(电源管理寄存器)的最高位,当设置SMOD的最高位为0时,串口方式1的波特率没有加倍,如果设置为1显然其他条件不变的情况下波特率会加倍,PCON的其他位跟这个程序就没多大的关系了呵呵,直接无视 ,要用到的时候再研究^-^。由于这个程序用到的是串口方式1,波特率是可以设置的,假如要设置波特率为9600bps的话,已知单片机的晶振为11.0592MHZ。因为溢出率就是溢出的频率即定时器每计多少个数产生一次溢出。这里采用定时器1来计数,因为定时器1有这样的特点即每发生一次溢出它会自动重装初值,不需要人为的去设定,显然这个特点可以提高溢出的精度,因此采用了定时器T1.来实现精确溢出。现在就是要求出定时器T1中的TH1和TL1装的初值是多少了,我们假设TH1和TL1装的初值都是X,因为TH1和TL1都是八位的所以最多能计数256个,其计数原理是:因为假设的是TH1和TL1都装的是X,那么每发生一次溢出后单片机会自动把TL1中的值重装入TH1中,开始进行第二次溢出了,就这样重复着进行下去。。。设所求的数为X,由前面分析可知定时器每计256-X个就溢出一次,而每记一个数的时间是一个机器周期,因为一个机器周期是12个时钟周期所以计一个数的时间为12/11.0592s,那么定时器溢出一次的时间为(256-x)x 12/11.0592s 那么溢出率就是时间的倒数为11.0592/(256-x)x12,这里SMOD取的是0,则波特率为 1/32 x【11.0592/(256-X)x12】=9600 这样就可以计算出X的值也就是TH1和TL1的值。而通常波特率都是固定的就是这个原因,因为这样计算出的X才会是整数。串行口控制寄存器SCON SM0,SM1是工作方式选择位 该程序中SM0=0,SM1=1初始化串口工作方式为1.REN是允许串行口接收位REN等于1时就允许了,该程序中初始化为1 最后是TI和RI 其中TI是发送中断位,在方式1下串行发送停止位的开始时,系统自动置1,然后申请中断。RI是接收中断位串行接收停止位时系统自动置1,申请中断,SCON 的其他的位与该程序无关,直接无视。等用到的时候再研究^_^编程前首先要进行串行口1工作的初始化操作主要是设置产生波特率的定时器1、串行口控制和中断控制。具体步骤如下:
1确定T1的工作方式(编程TMOD寄存器);
2计算T1的初值,装载TH1、TL1
3启动T1(编程TCON中的TR1位);
4确定串行口控制(编程SCON寄存器);
本帖子中包含更多资源
才可以下载或查看,没有帐号?
10:15:40  
22:39:16  
& & //因为定时器2是自动重装初值的因此不需要开定时器中断
这边应该是方式2吧,前面定模式的时候已经是用的定时器1了。方式2是自动重装初值
助理工程师
22:58:05  
本帖最后由 dianzi_fans 于
23:16 编辑
嗯,是方式二。自动重装的方式应该更精确
13:53:25  
楼主是否试过串口通信方式3带奇偶校验的?
为什么我用两个单片机做实验,一个很简单的程序,让甲发送信息(0x60)给乙,在没收到乙的反馈信息(0x50)前,甲一直发送数据,而乙接收到数据后就发送个反馈信息给甲。为什么乙每次都能收到甲的信息,但乙的反馈信息却传不回甲处?极少数情况能传回甲处。
另外,不知我的奇校验子程序是否有问题呢?能提供个串口通信带奇偶校验例程吗?!
这是我的程序:
甲单片机:
#include&reg52.h&
#define uchar unsigned char
#define uint unsigned int
sbit start=P0^0;//发光二极管,用来检测数据是否在发送
unsigned char a=0xff,i=100,b,
void& & delay(unsigned int m)& && && && &//延时程序
& & unsigned int i,j;
& & for(i=0; i&m; i++)
& && &&&for(j=0; j&110; j++);
bit jiaoyan(uchar m)//奇校验
for(i=0;i&8;i++)
&&tmp=tmp^m&0x01;
void main()
SCON=0xd0;//串口通信方式3
TMOD=0x20;//设置定时器1为工作方式2
TR1=1;//开计数器
ES=1;//开串口中断
while(jieshou!=0x50)
&&TB8=jiaoyan(0x60);
&&SBUF=0x60;
&&delay(1100);
&&start=0;
&&delay(1100);
&&start=1;
void ser0() interrupt 4//串口中断
&&temp=SBUF;
&&if(RB8==jiaoyan(temp))
& &jieshou=
//& &{jieshou=0}
乙单片机:
#include&reg52.h&
#define uchar unsigned char
#define uint unsigned int
sbit start=P0^0;//发光二极管,用来检测数据是否在发送
unsigned char a=0xff,i=100,b,jieshou,xh=1;
void& & delay(unsigned int m)& && && && &//延时程序
& & unsigned int i,j;
& & for(i=0; i&m; i++)
& && &&&for(j=0; j&110; j++);
bit jiaoyan(uchar m)//奇校验
for(i=0;i&8;i++)
&&tmp=tmp^m&0x01;
void main()
SCON=0xd0;//串口通信方式3
TMOD=0x20;//设置定时器1为工作方式2
TR1=1;//开计数器
ES=1;//开串口中断
while(jieshou!=0x60);
while(jieshou==0x60)(这个语句总是判断不到,当接收到甲的信号后,就直接跳到下一个语句停在while(1);处了,而不是进行循环发送,而我如果改成while(i--);就能进行循环,但要在发送几十次后才能成功让甲单片机收到信号)
&&TB8=jiaoyan(0x50);
&&SBUF=0x50;
&&start=0;
&&delay(2200);
&&start=1;
&&delay(1100);
void ser0() interrupt 4//串口中断
&&temp=SBUF;
&&if(RB8==jiaoyan(temp))
& &jieshou=
//& &{jieshou=0}
助理工程师
17:46:16  
本帖最后由 dianzi_fans 于
18:15 编辑
奇校验tmp=tmp^m&0x01;是啥意思?奇偶校验没怎么看过。
13:33:01  
本帖最后由 减肥陈 于
13:34 编辑
为什么一打开单片机 就会flag=1..
它显示I get 表示它进入了中断服务程序。但是,pc没有发送数据,单片机应该也没有发送数据到Pc。
为什么它会进入中断服务程序。
本帖子中包含更多资源
才可以下载或查看,没有帐号?
16:57:10  
本帖最后由 qilvkanxingxing 于
16:59 编辑
因为这是机器上电默认的。。。。。你那个单片机内有程序。。。
19:45:54  
在不同的串口调试助手下情况又不一样。
在stc_isp v479不会显示I get,在串口调试助手2.1就会显示。
我那板子是参照郭天祥51单片机的。郭天祥的书上截图也是一样,会出现I get.但是他没有解释。
08:41:34  
倒是看过郭天祥的视频里面的串口通信。你可以装其他的程序试试。。。
21:55:49  
我找以答案了。那本书在后面提到了这个现象,并进行了解释。
REN=1;这个要放在SM0 = 0,SM1 = 1;的后面。
22:54:50  
恩 ,是的。
17:09:51  
19:54:53  
09:40:12  
21:41:56  
得多学习啊
13:57:21  
观摩观摩,学习了
22:02:17  
书上有介绍
16:49:52  
19:54:28  
学习了下编程思路 呼啦啦
Powered by
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司求助 关于51单片机的串口数据处理问题|我爱单片机 - 数码之家
查看完整版本: [--
赞助商链接
本人刚刚接触51单片机,今天在写编程的时候遇到了一个关于串口数据处理的问题,要实现内容的大概是 :通过电脑的上位机用串口发送一个数字(10,20,25.....)给单片机,单片机把这个数字*316 * 2.099 *&&/ 25.4;的运算,先点亮一个led灯 ,然后延时计算出来的结果(ms)然后熄灭led灯,等待下一个串口发送的数值。&&&&&& 通讯程序可以实现,能通过上位机发送,也能接收到,但就是在数据处理方面出了问题始终不能解决。下面是写的大概程序[attachment=]#include &reg52.h&&&&&&&&&&&&& //此文件中定义了单片机的一些特殊功能寄存器typedef unsigned int u16;&&&&&&//对数据类型进行声明定义typedef unsigned char u8;sbit led=P2^2;&&&&&&&&//ledvoid UsartInit(){ SCON=0X50;&& //设置为工作方式1 TMOD=0X20;&& //设置计数器工作方式2 PCON=0X80;&& //波特率加倍 TH1=0XF3;&&&&//计数器初始值设置,波特率是4800的 TL1=0XF3; ES=1;&&&&&&//打开接收中断 EA=1;&&&&&&//打开总中断 TR1=1;&&&& //打开计数器}void delay(u16 i)&&&&&&&&&&//延时{ while(i--); }void Usart() interrupt 4{ u8 receiveDreceiveData=SBUF;//出去接收到的数据 RI = 0;//清除接收中断标志位 SBUF=receiveD//将接收到的数据放入到发送寄存器 while(!TI);&&&&//等待发送数据完成 TI=0;&&&&&& //清除发送完成标志位}void loop(){u16
bright= SBUF;&&//将bright值置为SBUFif(bright&0)&&&& //当bright&0时执行;{ bright= 316 * 2.099 * bright / 25.4;&& //这个地方是计算 ,也是数据处理,上位机发送的是字符或16进制?这个地方就不知道怎么处理了(要用到浮点数和整数的转换? 这是一个错误的的,只是想表达这个计算方法。问题就在这个地方!!!!!led=1;&&&&&&&& //点亮leddelay (bright);&&&&//暂停程序运行bright毫秒;}else{}led=0;&&&&&&&&&&&&&& //led熄灭;}void main()&&&&//个人感觉主函数也有问题 不知道是不是循环{
UsartInit();&&// 串口初始化 while(1) { loop();&&}}
&& 个人感觉这个代码有很多问题,希望有大神能帮忙解决和优化下 ,感谢大家了。
赞助商链接
u8 receiveD提到全局变量;中断里return一下。33. bright=&&receiveData;34.if(bright)&&&& //当bright&0时执行;35.{36.if(bright&2521)&&//U8,多余了。&&&& bright *= 26; 37.led=1;&&&&&&&&38.delay (bright); && bright=0;&& led = 0;39.}
赞助商链接
bright = (char)(316 * 2.099 * (double)(bright) / 25.4);强制类型转换
试试 float x = 316 * 2.099 * bright / 25.4;是数据类型的问题
几个问题:1,在两个函数中同时操作sbuf,而你根本无法确定哪个函数先运行。2每次bright=SBUF,都会有个数值,达不到你要的显示一段时间就停的效果。所以我把receiveDate提出来,然后return。3,RI清零后,再读sbuf,有可能新的数据已经传送过来,读到的不是原数据了。4,你试图把bright改变成浮点,但是最后又送到一个U16的delay函数。而且对于点灯来说,你无法分辨六万分之几秒的区别,所以我直接精简,用了整数26。5,灭灯后,没有延迟,也没有清bright。所以灭灯时间几乎等于0,效果就是灯一直在主循环里面亮着。
当串口接收到数据的时候,CPU进入中断函数处理,然后你直接把收到的再发出去,发完了SBUF也就空了,SBUF有数据的时候CPU一直在中断服务里运行,处理完后返回LOOP循环,但此时SBUF早已空了。所以LOOP里面的判断一直是else。bright= 316 * 2.099 * bright / 25.4; bright的值是结果值舍去小数,如果bright是浮点型或双精度型的就能存小数
化为整数运算,结果也取整数,包含四舍五入。 bright=((long)bright*316*)/10;
刚刚学习单片机,很多都是自己摸索的,可否优化下整个程序,供我参考学习,谢谢。
既然是从上位发到下位机,为什么不直接从上位机发送已计算好的数据到下位机呢?要知道下位机计算浮点是很耗资源的。 你把bright= 316 * 2.099 * bright / 25.4; 这行换成一个整数。比如32768试试,看代码效率有没有提高?
:既然是从上位发到下位机,为什么不直接从上位机发送已计算好的数据到下位机呢?要知道下位机计算浮点是很耗资源的。[表情] &( 23:24)&上位机输入数据下位机就可以直接出结果,如果算好了的话在发送比较麻烦。
:上位机输入数据下位机就可以直接出结果,如果算好了的话在发送比较麻烦。 ( 23:27) 不麻烦,你可以取整发送2个字节,非要发送浮点也可以,发3个字节,前2个字节是整数,后一字节上小数,甚到是4个字节!定好协议是很简单的。
:上位机输入数据下位机就可以直接出结果,如果算好了的话在发送比较麻烦。 ( 23:27) 直接出结果?这只是表面现象,你对比一下编译后的结果看看。16位无小数点整型运算、16位带小数点的乘除运算,对比一下效率。。另外,对于延时while(i--)常数来说,i=100与i=100.99有差别吗?
先搞清楚题目吧“通过电脑的上位机用串口发送一个数字(10,20,25.....)给单片机”这一个数字在通信中是1Byte还是2Byte?你现在的截图是2Byte。图上发“20”,实际发出的数据是 0x32 0x30。你把串口助手里面的“HEX发送”选上,这样实际发出的是1Byte内容是0x20。正在执行点灯以及延时的时候,要定个策略:是继续接收串口数据,执行新接收的指令?还是延时期间忽略新的指令?或者是指令都保存下来,然后按顺序执行?
:先搞清楚题目吧“通过电脑的上位机用串口发送一个数字(10,20,25.....)给单片机”这一个数字在通信中是1Byte还是2Byte?你现在的截图是2Byte。图上发“20”,实际发出的数据是 0x32 0x30。.......&( 11:56)&大概流程是:先通过调试助手发送一个数字,单片机计算和点亮led并延时 时间到后 led熄灭,这时再发送一个数字...如此循环下去。刚刚接触还是有许多不清楚的地方,能否帮忙优化下这个程序,供我学习学习,感谢。
:大概流程是:先通过调试助手发送一个数字,单片机计算和点亮led并延时 时间到后 led熄灭,这时再发送一个数字...如此循环下去。刚刚接触还是有许多不清楚的地方,能否帮忙优化下这个程序,供我学习学习,感谢。 ( 13:41) 在你原来程序基础上修改,可以满足你的功能要求。#include&reg52.h&typedef unsigned int u16;&&&&&&//对数据类型进行声明定义typedef unsigned char u8;sbit LED=P2^2;u8 receiveD//缓存变量u16&&&&&&&&//接收完成标志,void delay(u16 i)&&&&&&//延时{&&&&while(i--);} void init_uart()&&&&&&&&//晶振11.0592,波特率9600{&&&&TMOD=0X20;&&&&&&&& //定时器1工作模式寄存器&&&&TH1=0XFD;&&&&&&&& //timer high 1&&&&TL1=0XFD;&&&&&&&& //timer low&&1&&&&TR1=1;&&&&&&&&&&&& //定时器T1的运行控制位&&&&SCON=0X50;&&&&&&&& //串行控制寄存器&&&&EA=1;&&&&&&&&&&&&//CPU的总中断允许控制位&&&&ES=1;&&&&&&&&&&&&//串行口中断允许位&&&&&&&&} void main(){&&&&init_uart();&&&&while(1)&&&&{&&&&&&&&if(flag==1)&&&&&&&&//接收完成标志为1&&&&&&&&{&&&&&&&&&&&&ES=0;&&&&&&&&//关串口中断&&&&&&&&&&&&flag=0;&&&&&&&&//接收完成标志清0&&&&&&&&&&&&SBUF=receiveD&&&&&&&&//发送数据&&&&&&&&&&&&while(!TI);&&&&//等待发送中断请求标志位为1&&&&&&&&&&&&TI=0;&&&&&&&&//发送中断请求标志位清0&&&&&&&&&&&&bright=receiveD&&//将bright值置为receiveData&&&&&&&&&&&&if(bright&0)&&&& //当bright&0时执行;&&&&&&&&&&&&{&&&&//&&&&&&&&&&&&&&&&bright= 316 * 2.099 * bright / 25.4;//原算式//&&&&&&&&&&&&&&&&bright=(long)bright*316*4*10;//化整&&&&&&&&&&&&&&&&bright=((long)bright*316*+5)/10;//因运算过程超过16位,强制转换数据类型并简化算式,保留整数插入四舍五入&&&&&&&&&&&&&&&&LED=0;&&&&&&&&&&&& //低电平点亮led&&&&&&&&&&&&&&&&delay(bright);&&&&//暂停程序运行bright毫秒;&&&&&&&&&&&&&&&&LED=1;&&&&&&&&&&&&}&&&&&&&&&&&&else LED=1;&&&&&&&&&&&&&& //led熄灭;&&&&&&&&&&&&ES=1;&&&&&&&&//开串口中断&&&&&&&&}&&&&}} void UART_interrupt() interrupt 4 {&&&&RI=0;&&&& //接收中断请求标志位&&&&&&&&&&&&&&&& &&&&receiveData=SBUF;&&&&//获取SBUF接收到的数据&&&&flag=1;&&&&//接收完成标志置1&&&&&& }
:在你原来程序基础上修改,可以满足你的功能要求。#include&reg52.h&typedef unsigned int u16;&&&&&&//对数据类型进行声明定义typedef unsigned char u8;.......
通过串口助手发送的数字 是字符 单片机应该如何处理接收到的并进行计算?
不写代码,代码得自己写,不然不明白原理。下一个问题是1ms延时,给你网上找了一个说明。前提是AT89C52 @ 11.0592MHz。核心是&&for(ti=0;ti&112;ti++){}//1121ms的原理是这样的:机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作,如取指令、存储器读/写等。机器周期=6个状态周期=12个时钟周期。51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/ 晶振频率)= x μs。常用单片机的晶振为11.0592MHz,12MHz。其中11.0592MHz的晶振更容易产生各种标准的波特率,12MHz的一个机器周期为1 μs,便于精确延时。按照那个for语句的周期数,再乘112次,基本就是不太准确的1ms。
哦,明白了,但是你程序里写的延时不对。按你现在的接收程序,一次只能处理1个Byte。所以要按照HEX发送,一次1Byte,数值范围是(1-255)发送20的话,需要在发送框里填 16,然后选择HEX发送,这样就会把0x16也就是20发给单片机。先验证单片机收到的数据对不对,可以设个断点看看进来的数据是不是0x16.然后是计算:因为*316 * 2.099 *&&/ 25.4是一个常数,可以简化为*26.1135.如果你认可计算出来是522,那你就直接0x16*26就可以,这个就是522.然后是点灯,调用522次1ms延时,灭灯。点灯之前关掉串口中断,等延时结束了,灭灯之后再打开串口中断。
:通过串口助手发送的数字 是字符 单片机应该如何处理接收到的并进行计算? ( 15:04) 不清楚你要用那么复杂的计算要达到什么目的,如果以ms为单位作延时可以用带参数1ms延时程序,串口收到0x01~0xff数据直接带入delay可以延时1~255ms。你写的delay延时太短,不到10us。
查看完整版本: [--
Powered by
Time 0.059842 second(s),query:5 Gzip enabled51单片机 串口用 printf输出 ,当输出的数据类型是unsigned char的时候 电脑收到的数自动乘上了256_百度知道
51单片机 串口用 printf输出 ,当输出的数据类型是unsigned char的时候 电脑收到的数自动乘上了256
比如我unsigned char a=111;
printf(&%d& ,a);
电脑串口收到的字符是 a=28416.为啥???其他类型却不是,比如我用u int又正常,这是为啥
我有更好的答案
楼主你好。51单片机与标准C有区别:KEIL里扩展出了b,h,l来对输入字节宽的设置: (1)b八位 (2)h十六位 (3)l三十二位在Keil C51中用printf输出一个单字节变量时要使用%bd,如uprintf(&Current count: %bd\n&, counter);而在标准C语言中都是使用%d:printf(&Current count: %d\n&, counter);希望对你有帮助。
为您推荐:
其他类似问题
51单片机的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 c51 char 中的某一位 的文章

 

随机推荐