4631|1

1098

帖子

0

TA的资源

至上芯片

楼主
 

一个非常不错的串口程序 [复制链接]

//PC读MCU指令结构:(中断方式,ASCII码表示)
//帧: 帧头标志|帧类型|器件地址|启始地址|长度n|效验和|帧尾标志
//值: ’n’ ’y’| ’r’ | 0x01 | x | x | x |0x13 0x10
//字节数: 2 | 1 | 1 | 1 | 1 | 1 | 2
//求和:


/////////////////////////////////////////////////////////////////////
//公司名称:***
//模 块 名:protocol.c
//创 建 者:牛毅
//修 改 者:
//功能描述:中断方式:本程序为mcu的串口通讯提供(贞结构)函数接口,包括具体协议部分
//其他说明:只提供对AT89c51具体硬件的可靠访问接口
//版 本:1.0
//信 息:QQ 75011221 C51BBS匿名:niuyi
/////////////////////////////////////////////////////////////////////


#include
#include
//预定义
//帧
#define F_ST1 0x6e //帧头标志 n
#define F_ST2 0x79 //帧头标志 y
#define F_R 0x72 //帧类型 读
r
#define F_W 0x77 //帧类型 写
w
#define F_D 0x64 //帧类型 数据帧 d
#define F_B 0x62 //帧类型 写回应帧 b
#define F_C 0x63 //帧类型 重发命令帧 c
#define F_Q 0x71 //帧类型 放弃帧 q
#define F_ADDR 0x31 //器件地址 0-9
#define F_END 0x7a //帧尾标志 z
#define F_SPACE 0x30 //空标志 0
#define F_ERR1 0x31 //错误标志1,flagerr 1
#define F_ERR2 0x32 //错误标志2
2
//常数
#define S_MAXBUF 16 //接收/发送数据的最大缓存量
#define FIELD_MAXBUF 48 //最小场缓存,可以大于48字节,因为协议是以20字节为单
位传输的
#define communicationing P1_7//正在通讯(1)标志
#define ERRFRAME_MAX 5 //连续NOFRAME_CNT次帧不正确
#define ERR_NOCNTMAX_RESEND if( errframe_cnt<=ERRFRAME_MAX)resend_frame();
else errframe_cnt=communicationing=0;
//若超过
ERRFRAME_MAX 次则令通讯停止ERR_NOCNTMAX_RESEND

//public 变量
unsigned char databuf[FIELD_MAXBUF],errframe_cnt;
//函数

/////////////////////////////////////////////////////////////////////
//函 数 名:send()
//功能描述:向串口发送一个字符
//函数说明:
//调用函数:
//全局变量:
//输 入:ch-要发送的ASCII字符
//返 回:无
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
void send(unsigned char ch)
{SBUF=ch;while(TI==0);TI=0;}

/////////////////////////////////////////////////////////////////////
//函 数 名:receive()
//功能描述:从串口接收一个字符
//函数说明:
//调用函数:
//全局变量:
//输 入:无
//返 回:一个ASCII字符
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
unsigned char receive(void)
{while(RI==0);RI=0;return SBUF;}

/////////////////////////////////////////////////////////////////////
此帖出自单片机论坛
点赞 关注
 

回复
举报

1098

帖子

0

TA的资源

至上芯片

沙发
 

一个非常不错的串口程序

//函 数 名:CharToHex()
//功能描述:把ASCII字符转换为16进制
//函数说明:
//调用函数:
//全局变量:
//输 入:ASCII字符
//返 回:16进制
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
unsigned char CharToHex(unsigned char bChar){
if((bChar>=0x30)&&(bChar<=0x39))
bChar -= 0x30;
else if((bChar>=0x41)&&(bChar<=0x46))//大写字母
bChar -= 0x37;
else if((bChar>=0x61)&&(bChar<=0x66))//小写字母
bChar -= 0x57;
else bChar = 0xff;
return bChar;
}

/////////////////////////////////////////////////////////////////////
//函 数 名:HexToChar()
//功能描述:把16进制转换为ASCII字符
//函数说明:
//调用函数:
//全局变量:
//输 入:16进制
//返 回:ASCII字符
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
unsigned char HexToChar(unsigned char bHex){
if((bHex>=0)&&(bHex<=9))
bHex = 0x30;
else if((bHex>=10)&&(bHex<=15))//大写字母
bHex = 0x37;
else bHex = 0xff;
return bHex;
}

/////////////////////////////////////////////////////////////////////
//函 数 名:com_int()
//功能描述:初始化串口
//函数说明:默认其他参数为[baud_rate],n,8,1
//调用函数:
//全局变量:
//输 入:baud_rate 波特率
//返 回:无
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
void com_init(unsigned int baud_rate){
EA=1;ES=1;//ET1=1;
SCON = 0x50; /* 0x52;//SCON */
TMOD = 0x20; /*0x20;// TMOD */
TCON = 0x60; /*0x60;// TCON */
PCON=PCON&0x7f;
switch(baud_rate){ //波特率设置
case 1200:
TL1=0xe8;TH1=0Xe8;break;//1200
case 2400:
TL1=0xf4;TH1=0Xf4;break;//2400
case 4800:
TL1=0xfa;TH1=0Xfa;break;//4800
case 9600:
TL1=0xfd;TH1=0Xfd;break;//9600
case 19200:
PCON=PCON|0x80;TL1=0xfd;TH1=0Xfd;break;//19200
case 38400:
PCON=PCON|0x80;TL1=0xfe;TH1=0Xfe;break;//38400
default:
TL1=0xfd;TH1=0Xfd;break;//9600
}
}
/////////////////////////////////////////////////////////////////////
//函 数 名:resend_frame()
//功能描述:发送重发帧
//函数说明:通知PC重发
//调用函数:
//全局变量:
//输 入:无
//返 回:无
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
void resend_frame(void){
send(F_ST1);send(F_ST2);send(F_C);send(F_SPACE);send(F_SPACE);//发送效
验和
send(F_END);
}

/////////////////////////////////////////////////////////////////////
//函 数 名:quit_frame()
//功能描述:发送放弃帧
//函数说明:通知PC放弃通讯
//调用函数:
//全局变量:
//输 入:无
//返 回:无
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
void quit_frame(void){
send(F_ST1);send(F_ST2);send(F_Q);send(F_ERR1);send(F_ERR1);//发送效验

send(F_END);
}

/////////////////////////////////////////////////////////////////////
//函 数 名:com_int()
//功能描述:串口中断
//函数说明:
//调用函数:
//全局变量:
//输 入:无
//返 回:无
//设 计 者:牛毅
//修 改 者:
//版 本:
/////////////////////////////////////////////////////////////////////
void com_int()interrupt 4{
unsigned char i,csaddr,clen,csum,tempbuf[S_MAXBUF];
csum=0;
if(receive()==F_ST1){//是侦
if(receive()==F_ST2){//头判断完
communicationing=1;//设置通讯状态为正常 即启动通讯
switch(receive()){
case F_R://是读指令帧r
if(receive()==F_ADDR){P1_2=!P1_2;//地址
正确
csaddr=CharToHex(receive())<<4;csaddr =CharToHex
(receive());
clen=CharToHex(receive())
<<4;clen =CharToHex(receive());
csum=csaddr clen;
i=CharToHex(receive())
<<4;i =CharToHex(receive());
if(i==csum){//效验和正确
if(receive()
==F_END){//结束标志正确 //开始发送数据帧

csum=0;send(F_ST1);send(F_ST2);send(F_D);
send
(HexToChar((clen&0xf0)>>4));send(HexToChar(clen&0x0f));csum =clen;
for
(i=0;i
send(HexToChar((databuf[i csaddr]&0xf0)>>4));send(HexToChar(databuf
[i csaddr]&0x0f));

csum =databuf[i csaddr];
}
//if
(csum>127)csum-=128;
send
(HexToChar((csum&0xf0)>>4));send(HexToChar(csum&0x0f));send(F_END);

//发送数据帧完毕
P1_0=!
P1_0;
}else
{ERR_NOCNTMAX_RESEND break;}//结束标志错误
}else {ERR_NOCNTMAX_RESEND
break;}//效验和错误
}//地址不正确
break;
case F_W://是PC写指令帧w
if(receive()==F_ADDR){//地址正确
csaddr=CharToHex(receive())
<<4;csaddr =CharToHex(receive());
clen=CharToHex(receive())
<<4;clen =CharToHex(receive());
csum=csaddr clen;
for(i=0;i tempbuf[i csaddr]
=CharToHex(receive())<<4;tempbuf[i csaddr] =CharToHex(receive());
csum =tempbuf
[i csaddr];
}
i=CharToHex(receive())
<<4;i =CharToHex(receive());
if(csum!=i)
{ERR_NOCNTMAX_RESEND break;}//效验和错误
if(F_END!=receive())
{ERR_NOCNTMAX_RESEND break;}//结束标志错误
for
(i=csaddr;i }//从PC获得数据写完毕//开始发送写回应帧
send(F_ST1);send(F_ST2);send(F_B);send
(F_SPACE);send(F_SPACE);//发送效验和
send(F_END);//写回应帧发送完毕
P1_1=!P1_1;
break;
case F_Q://检测接收放弃帧
csaddr=receive();csum =csaddr;//csaddr
兼做放弃帧码标志
if(csaddr!=F_ERR1 && csaddr!=F_ERR2)
{ERR_NOCNTMAX_RESEND break;}
if(csum!=receive())
{ERR_NOCNTMAX_RESEND break;}
if(F_END!=receive())
{ERR_NOCNTMAX_RESEND break;}
communicationing=0;//出错退出通讯
break;
default:
resend_frame();//要求从发
}
}//忽略
}//忽略
if(!communicationing)quit_frame();//调用放弃帧,通知PC 放弃通讯
}
/////////////////////////////////////////////////////////////////

//主函数

/////////////////////////////////////////////////////////////////
void main(void){
unsigned char i;
for (i=0;i=i 0x30;
com_init(38400);
while(1){
/*可以处理非串口任务*/
}
}
此帖出自单片机论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表