51单片机从电脑串口接收10字节的数据,程序用c语言

51单片机从电脑串口接收10字节的数据,程序用c语言,第1张

可靠的接受程序!!从LZ 的display(a1a10)看出来这程序就不咋样,如果显示函数 还是 用 延时做的,可靠的接受程序给LZ 也是 白瞎……

以下是 UART 驱动程序

/10位异步收发串口通讯驱动——火柴天堂作品-20130119/

/源程序硬件环境:52单片机,110592MHz晶振,定时器1作为波特率发生器,通讯波特率9600 bit/s/

//

#define UART_H

#include"REG52h" //包含52头文件

#include"UARTh" //包含串口头文件

#define th1 0xfa //651us at 110592MHz Fosc for 8bit auto reload mode

static uchar UART_DataR; //串口接收数据寄存器

static uchar bdata Flag=0; //标志位 寄存器

sbit UART_ReFlag=Flag^0; //串口接收标志位 0:无数据 1:新数据

sbit UART_SendFlag=Flag^1; //串口发送标志位 0:空闲中 1:发送中

void UART()interrupt 4 //串口中断函数

{

if(RI) //若串口接收完成

{

RI=0; //清 串口接收溢出位

UART_DataR=SBUF; //将串口收到的数据存进 UART_DataR

UART_ReFlag=TRUE; //串口接收标志位 置位(有新数据)

}

if(TI) //若串口发送完成

{

TI=0; //清 串口发送溢出位

UART_SendFlag=FALSE; //清串口发送标志位(空闲中)

}

}

void UART_Init() //串口初始化函数

{

SCON=0x50; //选择通讯方式:10位异步收发,串口中断使能

PCON=0x80; //波特率倍频

TMOD&=0x0f; //定时器1控制位清0

TMOD|=0x20; //定时器1工作模式2(8位自重装,做波特率发生器)

TH1=th1; //定时器初值

TL1=th1; //定时器初值

TR1=1; //开始计时

ES=1; //允许串口中断

EA=1; //允许系统中断

}

bit UART_SendByte(uchar send_data) //串口发送字节函数,发送内容send_data,返回值:0 *** 作失败,1 *** 作成功

{

if(!UART_SendFlag) //若串口空闲中,则

{

SBUF=send_data; //将发送内容 送到 串口寄存器

UART_SendFlag=TRUE; //置位串口发送标志位(进入忙态)

return TRUE; //返回1, *** 作成功

}

return FALSE; //否则,返回0, *** 作失败

}

uchar ASCII_ToHex(uchar ascii_data) //ASCII 转 Hex 函数

{

uchar hex_data=0; //定义 Hex变量存储转换结果

if(ascii_data>='0' && ascii_data<='9') hex_data=ascii_data-'0'; //若 转换内容为 字符'0-9',则转成对应数字0-9

else if(ascii_data>='a' && ascii_data<='f') hex_data=ascii_data-'a'+10; //若 转换内容为 字符'a-f',则转成数字10-15

else if(ascii_data>='A' && ascii_data<='F') hex_data=ascii_data-'A'+10; //若 转换内容为 字符'A-F',则转成数字10-15

return hex_data; //返回转换结果,非以上字符,不在Hex(0-F)范围内,默认0

}

bit UART_ReadByte(uchar p_data,bit data_mode) //串口读字节函数,返回值0 无数据,1 有数据,将data_mode模式(ASCII_Mode或HEX_Mode)转成Hex结果存到p_data指向地址

{

if(!UART_ReFlag) return FALSE; //若无新数据,则返回 0(无数据)

UART_ReFlag=FALSE; //否则,清 串口接收标志位

if(data_mode==HEX_Mode) p_data=UART_DataR; //Hex模式,将串口接收结果存到p_data指向地址

if(data_mode==ASCII_Mode) p_data=ASCII_ToHex(UART_DataR); //ASCII模式,将串口接收结果转成Hex后,存到p_data指向地址

return TRUE; //返回 1(有数据)

}

你这串口接收子程序,只要接收到第一个字节的数据就一直在中断子程序中,然后等待接收其它数据了,

while(!RI); 这就是在等待接收其它数据了,接收完了以后又在中断子程序连续发送了。这么写程序是有很大弊病的,一旦进入中断程序,到最后发送结束,都一直在中断子程序中,那这个期间单片机是不能再做其它工作的,也就是不能再执行主程序了。

while(!RI);这就是查询方式等待接收数据,那又何必写成中断程序呢,不如直接写成查询程序了,同样下面的, while(!TI);这也明明是在查询方式发送,就不必要写在中断程序中了。

既然采用中断的方式,就是当接收到一个数据后才响应一次中断,保存这个数据,然后就立即从中断返回,这样,继续执行主程序,这样,接收数据和发送数据才不影响主程序。

同理,在中断程序发送一个字节的数据就立即从中断返回执行主程序,也不影响主程序的执行。

另外,更重要的一点就是while(!RI);,等待接收数据,如果不能收到数据就永远等待下去,假如通信线有故障,或者发送方有问题,不能发送数据了,那么将永远等待下去,这就相当于死机了,多可怕,写程序就怕这个事情发生的。

/   甲机串口程序:甲机向乙机发送控制命令字符,甲机同时接收乙机发送的数字,并显示在数码管上。/

#include<reg51h>

#define uchar unsigned char

#define uint unsigned int

sbit LED1=P1^0;

sbit LED2=P1^3;

sbit K1=P1^7;

uchar Operation_No=0;  // *** 作代码

//数码管代码

uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//延时

void DelayMS(uint ms)

{

uchari;

while(ms--)for(i=0;i<120;i++);

}

//向串口发送字符

void Putc_to_SerialPort(uchar c)

{

SBUF=c;

while(TI==0);

TI=0;

}

//主程序

void main()

{

LED1=LED2=1;

P0=0x00;

SCON=0x50;         //串口模式1,允许接收

TMOD=0x20;        //T1工作模式2

PCON=0x00;         //波特率不倍增

TH1=0xfd;

TL1=0xfd;

TI=RI=0;

TR1=1;

IE=0x90;        //允许串口中断

while(1)

{

DelayMS(100);

if(K1==0)      //按下K1时选择 *** 作代码0,1,2,3

{

while(K1==0);

Operation_No=(Operation_No+1)%4;

switch(Operation_No)    //根据 *** 作代码发送A/B/C或停止发送

{

case0:     Putc_to_SerialPort('X');

LED1=LED2=1;

break;

case1:     Putc_to_SerialPort('A');

LED1=~LED1;LED2=1;

break;

case2:     Putc_to_SerialPort('B');

LED2=~LED2;LED1=1;

break;

case3:     Putc_to_SerialPort('C');

LED1=~LED1;LED2=LED1;

break;

}

}

}

}

//甲机串口接收中断函数

void Serial_INT() interrupt   4

{

if(RI)

{

RI=0;

if(SBUF>=0&&SBUF<=9)P0=DSY_CODE[SBUF];

elseP0=0x00;

}

}

/ 乙机程序接收甲机发送字符并完成相应动作:乙机接收到甲机发送的信号后,根据相应信号控制LED完成不同闪烁动作。/

#include<reg51h>

#define uchar unsigned char

#define uint unsigned int

sbit LED1=P1^0;

sbit LED2=P1^3;

sbit K2=P1^7;

uchar NumX=-1;

//延时

void DelayMS(uint ms)

{

uchari;

while(ms--)for(i=0;i<120;i++);

}

//主程序

void main()

{

LED1=LED2=1;

SCON=0x50;         //串口模式1,允许接收

TMOD=0x20;        //T1工作模式2

TH1=0xfd;            //波特率9600

TL1=0xfd;

PCON=0x00;         //波特率不倍增

RI=TI=0;

TR1=1;

IE=0x90;

while(1)

{

DelayMS(100);

if(K2==0)

{

while(K2==0);

NumX=++NumX%11;   //产生0~10范围内的数字,其中10表示关闭

SBUF=NumX;

while(TI==0);

TI=0;

}

}

}

void Serial_INT() interrupt 4

{

if(RI)      //如收到则LED则动作

{

RI=0;

switch(SBUF)//根据所收到的不同命令字符完成不同动作

{

case'X':   LED1=LED2=1;break;          //全灭

case'A':   LED1=0;LED2=1;break;       //LED1亮

case'B':   LED2=0;LED1=1;break;       //LED2亮

case'C':   LED1=LED2=0;                  //全亮

}

}

}

以上就是关于51单片机从电脑串口接收10字节的数据,程序用c语言全部的内容,包括:51单片机从电脑串口接收10字节的数据,程序用c语言、51单片机串口接收多字符并存入数组的程序、两片单片机通过串口一发一收的C语言例程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9486094.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存