C51单片机串口通信的C程序

例子1

#include

#include

unsigned char ch;

bit read_flag= 0 ;

void init_serialcom( void ) //串口通信初始设定

{

SCON = 0x50 ; //UART为模式1,8位数据,允许接收

TMOD |= 0x20 ; //定时器1为模式2,8位自动重装

PCON |= 0x80 ; //SMOD=1;

TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHz

IE |= 0x90 ; //Enable Serial Interrupt

TR1 = 1 ; // timer 1 run

TI=1;

}

//向串口发送一个字符

void send_char_com( unsigned char ch)

{

SBUF=ch;

while (TI== 0);

TI= 0 ;

}

//串口接收中断函数

void serial () interrupt 4 using 3

{

if (RI)

{

RI = 0 ;

ch=SBUF;

read_flag= 1 ; //就置位取数标志

}

}

main()

{

init_serialcom(); //初始化串口

while ( 1 )

{

if (read_flag) //如果取数标志已置位,就将读到的数从串口发出

{

read_flag= 0 ; //取数标志清0

send_char_com(ch);

}

}

}

例子2

// 单片机串行口发送/接收程序,每接收到字节即发送出去

// 和微机相接后键入的字符回显示在屏幕上

// 可用此程序测试

//

#include

#define XTAL 11059200 // CUP 晶振频率

#define baudrate 9600 // 通信波特率

void main(void)

{

unsigned char c;

TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率

TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));

TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器0赋初值

SCON = 0x50;

PCON = 0x00;

TR1 = 1;

IE = 0x00; // 禁止任何中断

while(1)

{

while(RI == 0);

RI = 0;

c = SBUF; // 从缓冲区中把接收的字符放入c中

SBUF = c; // 要发送的字符放入缓冲区

while(TI == 0);

TI = 0;

}

}

例子3

//////////////////////////////////////////////////////////////////////////////////////////////////

//E51Pro.c

//Easy 51Pro编程器主程序,负责通讯,管理编程操作

///////////////////////////////////////////////////////////////////////////////////////////////////

#include

BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用

UINT nAddress;//ROM中地址计数

UINT nTimeOut;//超时计数

ProWork pw;//编程器一般操作

void Delay_us(BYTE nUs)//微秒级延时

{

TH0=0;

TL0=0;

TR0=1;

while(TL0

{

}

TR0=0;

}

void Delay_ms(UINT nMs)//豪秒级的延时

{

UINT n=0;

TR0=1;

while(n

{

TH0=0;

TL0=20;

while(TH0

{

}

n++;

}

TR0=0;

}

BOOL WaitComm()//等待上位机的命令,18字节

{

BYTE n=0;

RI=0;

while(!RI){}//等待第一个字节

ComBuf[n]=SBUF;

RI=0;

n++;

for(n;n

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)//后17个字节都有超时限制

return 0;

}

ComBuf[n]=SBUF;

RI=0;

}

return 1;

}

BOOL WaitResp()//等待上位机回应,1字节,有超时限制

{

nTimeOut=0;

RI=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>50000)

{

return 0;

}

}

RI=0;

ComBuf[0]=SBUF;

return 1;

}

BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制

{

BYTE n;

RI=0;

for(n=0;n

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)

{

return 0;

}

}

RI=0;

ComBuf[n]=SBUF;

}

return 1;

}

void SendData()//发送数据或回应操作完成,18字节

{

BYTE n=0;

for(n;n

{

TI=0;

SBUF=ComBuf[n];

while(!TI){}

TI=0;

}

}

void SendResp()//回应上位机1个字节,在写器件函数中使用

{

TI=0;

SBUF=ComBuf[0];

while(!TI){}

TI=0;

}

void SetVpp5V()//设置Vpp为5v

{

P3_4=0;

P3_3=0;

}

void SetVpp0V()//设置Vpp为0v

{

P3_3=0;

P3_4=1;

}

void SetVpp12V()//设置Vpp为12v

{

P3_4=0;

P3_3=1;

}

void RstPro()//编程器复位

{

pw.fpProOver();//直接编程结束

SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同

}

void ReadSign()//读特征字

{

pw.fpReadSign();

SendData();//通知上位机,送出读出器件特征字

}

void Erase()//擦除器件

{

pw.fpErase();

SendData();//通知上位机,擦除了器件

}

void Write()//写器件

{

BYTE n;

pw.fpInitPro();//编程前的准备工作

SendData();//回应上位机表示进入写器件状态,可以发来数据

while(1)

{

if(WaitData())//如果等待数据成功

{

if(ComBuf[0]==0x07)//判断是否继续写

{

for(n=2;n

{

if(!pw.fpWrite(ComBuf[n]))//

{

pw.fpProOver();//出错了就结束编程

ComBuf[0]=0xff;

SendResp();//回应上位机一个字节,表示写数据出错了

WaitData();//等待上位机的回应后就结束

return;

}

nAddress++;//下一个单元

}

ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续

SendResp();

}

else if(ComBuf[0]==0x00)//写器件结束

break;

else//可能是通讯出错了

{

pw.fpProOver();

return;

}

}

else//等待数据失败

{

pw.fpProOver();

return;

}

}

pw.fpProOver();//编程结束后的工作

Delay_ms(50);//延时等待上位机写线程结束

ComBuf[0]=0;//通知上位机编程器进入就绪

状态

SendData();

}

void Read()//读器件

{

BYTE n;

pw.fpInitPro();//先设置成编程状态

SendData();//回应上位机表示进入读状态

while(1)

{

if(WaitResp())//等待上位机回应1个字节

{

if(ComBuf[0]==0)//ComBuf[0]==0表示读结束

{

break;

}

else if(ComBuf[0]==0xff)//0xff表示重发

{

nAddress=nAddress-0x0010;

}

for(n=2;n

{

ComBuf[n]=pw.fpRead();//

nAddress++;//下一个单元

}

ComBuf[0]=6;//向上位机发送读出的数据块

SendData();

}

else

break;//等待回应失败

}

pw.fpProOver();//操作结束设置为运行状态

ComBuf[0]=0;//通知上位机编程器进入就绪状态

SendData();

}

void Lock()//写锁定位

{

pw.fpLock();

SendData();

}

///////////////////////////////////////////////////////////////////////////////////////////////////

//所支持的FID,请在这里继续添加

///////////////////////////////////////////////////////////////////////////////////////////////////

extern void PreparePro00();//FID=00:AT89C51编程器

extern void PreparePro01();//FID=01:AT89C2051编程器

extern void PreparePro02();//FID=02:AT89S51编程器

void main()

{

SP=0x60;

SetVpp5V();//先初始化Vpp为5v

SCON=0x00;

TCON=0x00;

//PCON=0x00;//波特率*2

IE=0x00;

//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0

// 0 0 1 0 0 0 0 1

TMOD=0x21;//T0用于延时程序

TH1=0xff;

TL1=0xff;//波特率28800*2,注意PCON

//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI

// 0 1 0 1 0 0 0 0

SCON=0x50;

TR1=1;

Delay_ms(1000);//延时1秒后编程器自举

ComBuf[0]=0;

SendData();

while(1)//串口通讯采用查询方式

{

if(!WaitComm())//如果超时,通讯出错

{

Delay_ms(500);

ComBuf[0]=0;//让编程器复位,使编程器就绪

}

switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针

{

case 0://at89c51编程器

PreparePro00();

break;

case 1://at89c2051编程器

PreparePro01();

break;

case 2://at89s51编程器

PreparePro02();

break;

//case 3:支持新器件时,请继续向下添加

// break;

//case 4:

// break;

default:

ComBuf[0]=0xff;

ComBuf[1]=0xff;//表示无效的操作

break;

}

switch(ComBuf[0])//根据操作ID跳到不同的操作函数

{

case 0x00:

RstPro();//编程器复位

break;

case 0x01:

ReadSign();//读特征字

break;

case 0x02:

Erase();//擦除器件

break;

case 0x03:

Write();//写器件

break;

case 0x04:

Read();//读器件

break;

case 0x05:

Lock();//写锁定位

break;

default:

SendData();

break;

}

}

}

例子4

void InitSerial(void)

{

TMOD = 0x20; // T1 方式2

PCON=0x00; // PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式

TH1 = TL1 = BAUD_9600; // BAUD: 9600

SCON = 0x50; // 串行通信方式1 REN=1 允许接收

ET1 = 0; // 不允许中断

TR1 = 1; // 开启定时器1

IE = 0; // 关闭所有中断允许位

memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN]

}

/********************************************************

**名称:SendByte()

**功能:串口发送一个字节

**输入:ucData

**返回:无

**说明:无

********************************************************/

void SendByte(unsigned char ucData)

{

SBUF = ucData;

while(!TI)

{

_CLRWDT_;

}

TI = 0;

}

例子1

#include

#include

unsigned char ch;

bit read_flag= 0 ;

void init_serialcom( void ) //串口通信初始设定

{

SCON = 0x50 ; //UART为模式1,8位数据,允许接收

TMOD |= 0x20 ; //定时器1为模式2,8位自动重装

PCON |= 0x80 ; //SMOD=1;

TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHz

IE |= 0x90 ; //Enable Serial Interrupt

TR1 = 1 ; // timer 1 run

TI=1;

}

//向串口发送一个字符

void send_char_com( unsigned char ch)

{

SBUF=ch;

while (TI== 0);

TI= 0 ;

}

//串口接收中断函数

void serial () interrupt 4 using 3

{

if (RI)

{

RI = 0 ;

ch=SBUF;

read_flag= 1 ; //就置位取数标志

}

}

main()

{

init_serialcom(); //初始化串口

while ( 1 )

{

if (read_flag) //如果取数标志已置位,就将读到的数从串口发出

{

read_flag= 0 ; //取数标志清0

send_char_com(ch);

}

}

}

例子2

// 单片机串行口发送/接收程序,每接收到字节即发送出去

// 和微机相接后键入的字符回显示在屏幕上

// 可用此程序测试

//

#include

#define XTAL 11059200 // CUP 晶振频率

#define baudrate 9600 // 通信波特率

void main(void)

{

unsigned char c;

TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率

TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));

TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器0赋初值

SCON = 0x50;

PCON = 0x00;

TR1 = 1;

IE = 0x00; // 禁止任何中断

while(1)

{

while(RI == 0);

RI = 0;

c = SBUF; // 从缓冲区中把接收的字符放入c中

SBUF = c; // 要发送的字符放入缓冲区

while(TI == 0);

TI = 0;

}

}

例子3

//////////////////////////////////////////////////////////////////////////////////////////////////

//E51Pro.c

//Easy 51Pro编程器主程序,负责通讯,管理编程操作

///////////////////////////////////////////////////////////////////////////////////////////////////

#include

BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用

UINT nAddress;//ROM中地址计数

UINT nTimeOut;//超时计数

ProWork pw;//编程器一般操作

void Delay_us(BYTE nUs)//微秒级延时

{

TH0=0;

TL0=0;

TR0=1;

while(TL0

{

}

TR0=0;

}

void Delay_ms(UINT nMs)//豪秒级的延时

{

UINT n=0;

TR0=1;

while(n

{

TH0=0;

TL0=20;

while(TH0

{

}

n++;

}

TR0=0;

}

BOOL WaitComm()//等待上位机的命令,18字节

{

BYTE n=0;

RI=0;

while(!RI){}//等待第一个字节

ComBuf[n]=SBUF;

RI=0;

n++;

for(n;n

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)//后17个字节都有超时限制

return 0;

}

ComBuf[n]=SBUF;

RI=0;

}

return 1;

}

BOOL WaitResp()//等待上位机回应,1字节,有超时限制

{

nTimeOut=0;

RI=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>50000)

{

return 0;

}

}

RI=0;

ComBuf[0]=SBUF;

return 1;

}

BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制

{

BYTE n;

RI=0;

for(n=0;n

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)

{

return 0;

}

}

RI=0;

ComBuf[n]=SBUF;

}

return 1;

}

void SendData()//发送数据或回应操作完成,18字节

{

BYTE n=0;

for(n;n

{

TI=0;

SBUF=ComBuf[n];

while(!TI){}

TI=0;

}

}

void SendResp()//回应上位机1个字节,在写器件函数中使用

{

TI=0;

SBUF=ComBuf[0];

while(!TI){}

TI=0;

}

void SetVpp5V()//设置Vpp为5v

{

P3_4=0;

P3_3=0;

}

void SetVpp0V()//设置Vpp为0v

{

P3_3=0;

P3_4=1;

}

void SetVpp12V()//设置Vpp为12v

{

P3_4=0;

P3_3=1;

}

void RstPro()//编程器复位

{

pw.fpProOver();//直接编程结束

SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同

}

void ReadSign()//读特征字

{

pw.fpReadSign();

SendData();//通知上位机,送出读出器件特征字

}

void Erase()//擦除器件

{

pw.fpErase();

SendData();//通知上位机,擦除了器件

}

void Write()//写器件

{

BYTE n;

pw.fpInitPro();//编程前的准备工作

SendData();//回应上位机表示进入写器件状态,可以发来数据

while(1)

{

if(WaitData())//如果等待数据成功

{

if(ComBuf[0]==0x07)//判断是否继续写

{

for(n=2;n

{

if(!pw.fpWrite(ComBuf[n]))//

{

pw.fpProOver();//出错了就结束编程

ComBuf[0]=0xff;

SendResp();//回应上位机一个字节,表示写数据出错了

WaitData();//等待上位机的回应后就结束

return;

}

nAddress++;//下一个单元

}

ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续

SendResp();

}

else if(ComBuf[0]==0x00)//写器件结束

break;

else//可能是通讯出错了

{

pw.fpProOver();

return;

}

}

else//等待数据失败

{

pw.fpProOver();

return;

}

}

pw.fpProOver();//编程结束后的工作

Delay_ms(50);//延时等待上位机写线程结束

ComBuf[0]=0;//通知上位机编程器进入就绪

状态

SendData();

}

void Read()//读器件

{

BYTE n;

pw.fpInitPro();//先设置成编程状态

SendData();//回应上位机表示进入读状态

while(1)

{

if(WaitResp())//等待上位机回应1个字节

{

if(ComBuf[0]==0)//ComBuf[0]==0表示读结束

{

break;

}

else if(ComBuf[0]==0xff)//0xff表示重发

{

nAddress=nAddress-0x0010;

}

for(n=2;n

{

ComBuf[n]=pw.fpRead();//

nAddress++;//下一个单元

}

ComBuf[0]=6;//向上位机发送读出的数据块

SendData();

}

else

break;//等待回应失败

}

pw.fpProOver();//操作结束设置为运行状态

ComBuf[0]=0;//通知上位机编程器进入就绪状态

SendData();

}

void Lock()//写锁定位

{

pw.fpLock();

SendData();

}

///////////////////////////////////////////////////////////////////////////////////////////////////

//所支持的FID,请在这里继续添加

///////////////////////////////////////////////////////////////////////////////////////////////////

extern void PreparePro00();//FID=00:AT89C51编程器

extern void PreparePro01();//FID=01:AT89C2051编程器

extern void PreparePro02();//FID=02:AT89S51编程器

void main()

{

SP=0x60;

SetVpp5V();//先初始化Vpp为5v

SCON=0x00;

TCON=0x00;

//PCON=0x00;//波特率*2

IE=0x00;

//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0

// 0 0 1 0 0 0 0 1

TMOD=0x21;//T0用于延时程序

TH1=0xff;

TL1=0xff;//波特率28800*2,注意PCON

//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI

// 0 1 0 1 0 0 0 0

SCON=0x50;

TR1=1;

Delay_ms(1000);//延时1秒后编程器自举

ComBuf[0]=0;

SendData();

while(1)//串口通讯采用查询方式

{

if(!WaitComm())//如果超时,通讯出错

{

Delay_ms(500);

ComBuf[0]=0;//让编程器复位,使编程器就绪

}

switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针

{

case 0://at89c51编程器

PreparePro00();

break;

case 1://at89c2051编程器

PreparePro01();

break;

case 2://at89s51编程器

PreparePro02();

break;

//case 3:支持新器件时,请继续向下添加

// break;

//case 4:

// break;

default:

ComBuf[0]=0xff;

ComBuf[1]=0xff;//表示无效的操作

break;

}

switch(ComBuf[0])//根据操作ID跳到不同的操作函数

{

case 0x00:

RstPro();//编程器复位

break;

case 0x01:

ReadSign();//读特征字

break;

case 0x02:

Erase();//擦除器件

break;

case 0x03:

Write();//写器件

break;

case 0x04:

Read();//读器件

break;

case 0x05:

Lock();//写锁定位

break;

default:

SendData();

break;

}

}

}

例子4

void InitSerial(void)

{

TMOD = 0x20; // T1 方式2

PCON=0x00; // PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式

TH1 = TL1 = BAUD_9600; // BAUD: 9600

SCON = 0x50; // 串行通信方式1 REN=1 允许接收

ET1 = 0; // 不允许中断

TR1 = 1; // 开启定时器1

IE = 0; // 关闭所有中断允许位

memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN]

}

/********************************************************

**名称:SendByte()

**功能:串口发送一个字节

**输入:ucData

**返回:无

**说明:无

********************************************************/

void SendByte(unsigned char ucData)

{

SBUF = ucData;

while(!TI)

{

_CLRWDT_;

}

TI = 0;

}


相关内容

  • C51单片机串口通信
  • /* #################################################### C51单片机串口通信控制与信号反馈 作者:nathen_zhang 博客:http://hi.baidu.com/nathen 将单片机与电脑串口相连,电脑发送数0-9到单片机,单片机相应 ...

  • 湖南大学工程训练项目报告-蓝牙小车
  • 蓝牙小车报告 小组成员: 班级: 联系方式: 目录 一. 引言 ------------------------------1 二. 总体方案 ------------------------------1 三. 电路与程序设计 ------------------------------3 四. ...

  • 出租车计费器
  • 能力拓展训练任务书 学生姓名: 郑子茗 专业班级: 自动化1101班 指导教师: 孙晓明 工作单位: 自动化学院 题 目: 出租车计费器设计 初始条件:计算机.Max+plusⅡ.EDA实验箱. 要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 设计一个出租车计费器 ...

  • 单片机期末考试试题
  • 物理与电气工程学院C51单片机试卷4 一.填空题(每小题1分,共45分) 1.串行口方式2接收到的第9位数据送 寄存器的 位中保存. 2.MCS-51系列单片机为 位单片机. 3.8031的中断源有 . . . 中断优先级. 4.MCS-51系列单片机的典型芯片分别为 . . . 5.利用8255A ...

  • 关于51单片机论文
  • 西安邮电学院 毕 业 设 计(论 文) 题 目: 院 (系): 专 业: 班 级: 学生姓名: 导师姓名: 职称: 1.绪 论 二十世纪跨越了三个"电"的时代,即电气时代.电子时代和现已进入的电脑时代.不过,这种电脑,通常是指个人计算机,简称PC机.它由主机.键盘.显示器等组成. ...

  • 单片机串行通信实验
  • 单片机实验报告 实验名称: 姓 名: 学 号: 班 级: 实验时间: 串行通信实验 高知明 110404320 通信3 2014-6-11 南京理工大学紫金学院电光系 一. 实验目的(四号+黑体) 1. 理解单片机串行口的工作原理: 2. 学习使用单片机的TXD\RXD口: 3. 了解MAX232芯 ...

  • 基于51单片机的智能窗帘控制系统设计与实现
  • 项目编号 江南大学物联网工程学院 大学生创新训练计划结题报告 项目名称 基于51单片机的智能窗帘控制系统设计与实现 秦 晶 电气工程及其自动化 物联网工程学院 [1**********] [email protected] 2011/11-2012/05 肖 永 松 工 程 师 [1***** ...

  • 电子信息工程课程设计
  • 课程设计文档格式 一.课程设计书写规范 1. 数字 除习惯用中文数字表示的以外, 一般均采用阿拉伯数字.年份一概写全数,如2004年不能写成04年. 2. 公式 原则上居中书写. 公式序号按章.按阿拉伯数字阿拉伯数字编排,如第1章第一个公式序号为"(1.1)",第2章第一个公式序 ...

  • 基于单片机GPRS通信系统的计毕业设计好
  • 基于单片机GPRS通信系统的计 摘要 GPRS(通用分组无线电业务)是利用包交换的概念发展的一套无线传输方式,GPRS网络是基于现有的GSM(全球移动通信系统)网络实现的,在现有的GSM网络中需要增加一些节点,如GGSN(GPRS网关支持节点)和SGSN(GPRS服务支持节点).SGSN的主要作用是 ...