- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
51 单片机串口通信
1./*打开串口调试程序,将波特率设置为 9600,无奇偶校验晶振 11.0592MHz,发送和接收使用的格式相同,如都使
用字符型格式,在发送框输入 hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确 */
#include <REG52.H> /*主程序*/
TL1=0XFD; 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 ;
RI=0; for(n=0;n<=17;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<=17;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
TL1=0XFD;
TR1 = 1; /* TR1: timer 1 run */
EA = 1; /*打开总中断*/
ES = 1;
/*打开串口中断*/
while (1)
/*主循环不做任何动作*/
{
}
} void UART_SER (void) interrupt 4 //串行中断服务程序
{
unsigned char Temp; //定义临时变量
///////////////////////////////////////////////////////////////////////////////// //所支持的 FID,请在这里继续添加
///////////////////////////////////////////////////////////////////////////// extern void PreparePro00();//FID=00:AT89C51 编程器 extern void PreparePro01();//FID=01:AT89C2051 编程器 extern void PreparePro02();//FID=02:AT89S51 编程器
void main (void)
{ SCON = 0x50; /* SCON: 模式 1, 8-bit UART, 使能接收*/
TMOD = 0x20; /* TMOD: timer 1, mode 2,
8-bit reload*/
TH1 = 0xFD; /* TH1: reload value for 9600 baud @ 11.0592MHz */
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<=17;n++)//ComBuf[2~17]保存读出的数据块 { ComBuf[n]=pw.fpRead();//<<<<<<<<<<调用写该器件一个单元的函数 nAddress++;//下一个单元 } ComBuf[0]=6;//向上位机发送读出的数据块
}
3.// 单片机串行口发送/接收程序,每接收到字节即发送出去
// 和微机相接后键入的字符回显示在屏幕上
// 可用此程序测试
#include <reg51.h> #define XTAL 11059200
// CUP 晶振频率
#define baudrate 9600 // 通信波特率
void main(void)
pw.fpReadSign(); SendData();//通知上位机,送出读出器件特征字 }
void Erase()//擦除器件 {
pw.fpErase(); SendData();//通知上位机,擦除了器件 }
void Write()//写器件 {
BYTE n; pw.fpInitPro();//编程前的准备工作 SendData();//回应上位机表示进入写器件状态,
// 定时器 0 赋初值
//E51Pro.c
//Easy 51Pro 编程器主程序,负责通讯,管理编程操作
/////////////////////////////////////////////////////////////////////////
#include <E51Pro.h> BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用 UINT nAddress;//ROM 中地址计数 UINT nTimeOut;//超时计数 ProWork pw;//编程器一般操作 void Delay_us(BYTE nUs)//微秒级延时<255us {
TH0=0; TL0=0; TR0=1; while(TL0<nUs)//利用 T0 做定时计数器,循环采样,直到达到定时值 { } TR0=0; } void Delay_ms(UINT nMs)//豪秒级的延时<65535ms { UINT n=0; TR0=1; while(n<nMs)////利用 T0 做定时计数器,循环采样,直到达到定时值 {
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;
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
#include <reg51.h> #include <string.h> unsignΒιβλιοθήκη Baidud 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
} 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); } }
可以发来数据 while(1) {
if(WaitData())//如果等待数据成功 { if(ComBuf[0]==0x07)//判断是否继续写 {
for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块 { if(!pw.fpWrite(ComBuf[n]))//<<< <<<<<<调用写该器件一个单元的函数 {
{
unsigned char c;
TMOD = 0x20; // 定时器 1 工作于 8 位自动重载模式, 用于产生波特率
TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));
TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); SCON = 0x50; PCON = 0x00; TR1 = 1; IE = 0x00; // 禁止任何中断 while(1) {
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();
}
{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
TH0=0; TL0=20; while(TH0<4) {
} n++; } TR0=0; } BOOL WaitComm()//等待上位机的命令,18 字节 { BYTE n=0; RI=0; while(!RI){}//等待第一个字节 ComBuf[n]=SBUF; RI=0; n++; for(n;n<=17;n++) { nTimeOut=0; while(!RI) { nTimeOut++; if(nTimeOut>10000)//后 17 个字节都有超时限制
if(RI)
//判断是接收中断产生
{ RI=0; Temp=SBUF; P1=Temp; SBUF=Temp;
//标志位清零 //读入缓冲区的值
//把值输出到 P1 口,用于观察 //把接收到的值再发回电脑端
} if(TI)
//如果是发送标志位,清零
TI=0;
}
2.51 单片机与电脑串口通信的 C 程序,最好是中断方式的