一个非常不错的串口程序

发布者:神秘行者最新更新时间:2016-11-23 来源: eefocus关键字:串口程序  AT89c51 手机看文章 扫描二维码
随时随地手机看文章

//PC读MCU指令结构:(中断方式,ASCII码表示)

//帧:   帧头标志|  帧类型|   器件地址|      启始地址|          长度n|      效验和|     帧尾标志

//值:    ’n’       ’y’       |     ’ r’      |  0x01  |      x    |  x     |   x  |    0x13 0x10

//字节数:   2   |  1   |    1   |   1    |  1  |   1  |   2

//求和:

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

//功能描述:中断方式:本程序为mcu的串口通讯提供(贞结构)函数接口,包括具体协议部分

//其他说明:只提供对AT89c51具体硬件的可靠访问接口

//版    本:1.0

//信    息:

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

#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;}

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

//函 数 名: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<>

com_init(38400);

while(1){

/*可以处理非串口任务*/

}

}


关键字:串口程序  AT89c51 引用地址:一个非常不错的串口程序

上一篇:单片机之按键学习
下一篇:74HC164控制数码管显示

推荐阅读最新更新时间:2024-03-16 15:21

串口通信USART-AVR程序代码
#include #include #define RXB8 1 #define TXB8 0 #define UPE 2 #define OVR 3 #define FE 4 #define UDRE 5 #define RXC 7 #define FRAMING_ERROR (1 FE) #define PARITY_ERROR (1 UPE) #define DATA_OVERRUN (1 OVR) #define DATA_REGISTER_EMPTY (1 UDRE) #define RX_COMPLETE (1 RXC) // USART Receiver buffer #define RX_BUFFER_
[单片机]
基于AT89C51单片机的PT100温度检测系统
一.系统概述 系统使用的模块有AT89C51单片机+8位共阴数码管+ADC0804模数转换+PT100温度检测。 系统内使用AT89C51单片机作为主控,使用PT100来检测温度,检测到的温度模拟信号会通过ADC0804进行数据转换,转换得到的数据经过单片机的处理后传输到数码管上进行显示,显示屏能够显示的温度精度为0.1℃。 二.仿真概述 1.8位共阴极书数码管显示检测到的温度数据。 2.通过PT100温度传感器检测环境温度,通过调节电位器来模拟温度的改变。 3.通过ADC0804可以将采集到的模拟温度数据转换为数字温度数据。 三.程序设计 使用Keil 51进行程序设计,打开Proteus时程序是默认烧录的状
[单片机]
基于<font color='red'>AT89C51</font>单片机的PT100温度检测系统
AT89C51单片机十字路口交通灯设计
制作出来的实物图如下: 这是一个十字路口的交通灯设计仿真原理图如下(proteus仿真工程文件可到本帖附件中下载) keil单片机源程序如下: #include include.h sbit NS_GRE = P2^5; sbit NS_YEL = P2^4; sbit NS_RED = P2^3; sbit EW_GRE = P2^2; sbit EW_YEL = P2^1; sbit EW_RED = P2^0; uint8 EW_Timer = unused8; //东西方向红灯定时器 uint8 NS_Timer = unused8; //南北方向红灯定时器 uint8 YEL_T
[单片机]
<font color='red'>AT89C51</font>单片机十字路口交通灯设计
基于AT89C51单片机设计的简易智能机器人的设计
简介:随着微电子技术的不断发展,微处理器芯片的集成程度越来越高,单片机已可以在一块芯片上同时集成CPU、存储器、定时器/计数器、并行和串行接口、看门狗、前置放大器、A/D转换器、D/A转换器等多种电路,这就很容易将计算机技术与测量控制技术结合,组成智能化测量控制系统。这种技术促使机器人技术也有了突飞猛进的发展,目前人们已经完全可以设计并制造出具有某些特殊功能的简易智能机器人。 1 设计思想与总体方案 1.1 简易智能机器人的设计思想 本机器人能在任意区域内沿引导线行走,自动绕障,在有光源引导的条件下能沿光源行走。同时,能检测埋在地下的金属片,发出声光指示信息,并能实时存储、显示检测到的断点数目以及各断点至起跑线间的距离
[单片机]
基于<font color='red'>AT89C51</font>单片机设计的简易智能机器人的设计
数字反馈控制技术实现直流稳压电源设计
  引言   直流稳压电源是电子技术领域不可缺少的设备。目前, 直流稳压电源 已朝着多功能和数字化的方向发展,本文以单片机为核心,结合数字反馈控制技术。该电路具有电压调整简便,读数直观,电压输出稳定,便于智能化管理的特点,有效地克服了传统电源的不足。   1 系统功能系统   电压调节范围为0一12V,最大输出电流2A,具有过载和短路保护功能。数字显示有4位,其中1位功能显示,另3位显示输出电压以及电路参数设定值。键盘设有4个键,功能选择键,步进增减键以及确认键。功能选择键用于启动参数设定状态,步进增减键用于设定参数数值,确认键用于输入设定值电源开机设定值为前次使用值。此时按键,则电压显示值出现闪烁现象,表示进人参数设定状态
[单片机]
数字反馈控制技术实现直流稳压电源设计
STM32 USART串口的使用方法和程序
通用同步异步收发器(USART)提供了一种灵活的方法来与使用工业标准NR 异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择,支持同步单向通信和半双工单线通信。 1、STM32固件库使用外围设备的主要思路 在STM32中,外围设备的配置思路比较固定。首先是使能相关的时钟,一方面是设备本身的时钟,另一方面如果设备通过IO口输出还需要使能IO口的时钟;最后如果对应的IO口是复用功能的IO口,则还必须使能AFIO的时钟。 其次是配置GPIO,GPIO的各种属性由硬件手册的AFIO一章详细规定,较为简单。 接着相关设备需要如果需要使用中断功能,必须先配置中断优先级,后文详述。 然后是配
[单片机]
AT89C51制作的简单计数器
网上好友大侠画了一个计数器的电路图让我帮忙写个软件,抽空写了一个。他做好了电路我就把程序给他烧写实验,稍微修改后达到他的要求。   图中可以看到本制作的主要核心电路是用AT89C51组成的按键取值电路,S3S4分别控制计数值的加减。数码管使用的是共阳极通过3906控制。   这个计数器主要用于对键的按键次数计数,用于鼠标中的微按钮或其它按钮做QC测试用。所以在软件中用了取两次定时中断的键值做比较以达到简单防抖动和取健值的目的。读者朋友可以自行修改程序以适合自己的电路。本计数器的计数范围为0-999999,最大的频率为50Hz,当然这些参数都可以根据需要调整。程序使用的是汇编延时程序,可以改用C写,没有任何关系只是我偷懒从旧
[单片机]
<font color='red'>AT89C51</font>制作的简单计数器
基于AT89C51的数据采集系统设计新方法
0 引言 近年来,随着制造技术的发展,单片机的价格越来越低,性能却不断提升,因而其应用范围也越来越广。然而在开发基于单片机的应用系统时,传统方法一般都需要大量的硬件设备,这些设备极易损坏而且携带不方便。为此,本文基于AT89C51数据采集系统详细说明了如何利用Pro-teus和两款串口仿真软件来进行单片机程序及外围电路的仿真设计。采用该方法可以大大简化硬件电路测试和系统调试过程,对单片机系统开发具有指导意义。本文介绍的基于AT89C5l单片机的数据采集系统能实现16路信号输入,每一路都是0~10 mV的信号,每秒钟采集一遍,从而将数据传给上位PC计算机。 1 硬件设计 1.1 主控芯片 AT89C51是一种带有4 KB闪烁
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved