单片机串口通信课程设计

  • 格式:docx
  • 大小:352.49 KB
  • 文档页数:20

目录摘要 (I)1 基本原理 (1)1.1串行通信 (1)1.2 数码管动态显示 (1)1.3定时器 (1)1.4 LCD1602 (2)2 设计过程 (3)2.1设计思路 (3)2.2电路图 (4)2.3 流程图 (6)3程序代码 (7)3.1主程序 (7)3.2 串口通信程序 (9)3.3 数码管显示 (10)3.4 定时程序 (12)4 运行结果 (13)5 心得体会 (16)参考文献 (17)课程设计任务书学生姓名:专业班级:指导教师:工作单位:题目: PC和单片机的串行双工通信初始条件:具备单片机原理的理论知识和实践能力;熟悉51单片机的CPU 结构和指令系统;熟悉相关常用接口电路的设计使用方法。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1)利用串口设计4位静态数码管显示器,要求4位显示器上每隔1s交替显示“0123”和“4567”。

2)完成PC和单片机的串行双工通信,单片机的P1口接一共阴极数码管,阴极接地。

要求PC键盘每按“0~9”数字键能发送到单片机,并显示在单片机接的数码管上,单片机发送一串字符串能显示在PC的屏幕上,采用查询方式。

波特率为1200。

时间安排:一周,其中2天程序设计,2天程序调试,1天完成课程设计报告书及答辩指导教师签名:年月日系主任(或责任教师)签名:年月日摘要本设计运用51单片机设计了一个能和PC进行全双工通信的程序,能由单片机向PC 发送字符串,当按PC上的数字键时,能在单片机上的数码管上显示相应数字,并且单片机的其他数码管能每隔1s交替显示0123和4567还扩展了用lcd1602显示来自PC端的任意字符,并能统计和显示发送和接受的字符数。

程序采用C语言分模块编写,并用proteus 仿真通过。

关键词:单片机;串行通信;数码管1 基本原理1.1串行通信单片机的串行通信使用的是异步串行通信。

串行接口电路为用户提供了两个串行口缓冲寄存器(SBUF),一个称为发送缓存器,它的用途是接收片内总线送来的数据,即发送缓冲器只能写不能读。

发送缓冲器中的数据通过TXD引脚向外传送。

另一个称为接收缓冲器,它的用途是向片内总线发送数据,即接收缓冲器只能读不能写。

接收缓冲器通过RXD引脚接收数据。

因为这两个缓冲器一个只能写,一个只能读,所以共用一个地址99H。

串行口控制寄存器SCON是MCS-51单片机的一个可位寻址的专用寄存器,用于串行数据通信的控制。

单元地址为98H,位地址为98H~9FH。

寄存器的内容及位地址表示如下:SM0 、SM1——串行口工作方式选择位M2——允许方式2、3的多机通信控制位REN——允许接收位TB8——发送数据位8,RB8——接收数据位8,TI——发送中断标志位RI——接收中断标志位.。

表1 SCON控制字1.2 数码管动态显示动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效,这样可以节省引脚。

所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。

1.3定时器MCS-51单片机内部共有两个16位可编程的定时器/计数器,即定时器T0和定时器T1它们既有定时功能又有计数功能。

(1)定时器控制寄存器(TCON)TF0/TF1:查询方式:禁止中断,软件查询TF0的值,软件清“0”中断方式:硬件查询TF0的值,硬件自动清“0”(2)工作方式寄存器(TMOD )功能:确定定时器的工作方式及功能选择。

GATE :门控位_/C T 功能选择位 M0M1工作方式选择位1.4 LCD1602字符型液晶模块是一种用5x7 点阵图形来显示字符的液晶显示器,根据显示的容量可以分为1 行16 个字、2 行16个字、2 行20个字等等,这里采用的是2 行16 个字的1602 液晶模块 1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,内部的控制器共有11 条控制指令它的读写操作、屏幕和光标的操作都是通过指令编程来实现的。

程序在开始时对液晶模块功能进行了初始化设置,约定了显示格式。

注意显示字符时光标是自动右移的,无需人工干预,每次输入指令都先调用判断液晶模块是否忙的子程序DELAY ,然后输入显示位置的地址例如0C0H ,最后输入要显示的字符例如A 的代码41H 。

表2 TCON 控制字表3 TMOD 控制字2 设计过程2.1设计思路目前手头上有一个现成的51单片机开发板,上面有6个数码管,独立键盘等资源,根据题目要求可以分模块设计。

(1) 数码管显示:题目要求数码管数码管显示器每隔1s交替显示“0123”和“4567”,同时能按PC上的数字键能显示对于数字,6个数码显示够用。

由于字选端口和位选端口都通过74HC573与P0口相连,采用分时操作的方法,先打开与字选端口锁存器,向P0口写入位选码,接着锁存,然后打开位选端口锁存器,向P0口写入字形码,再锁存,延时一定时间后在操作其他几个数码管。

为保持数码管不熄灭,所以数码管显示程序要一直循环。

(2) 串行通信:要实现PC和单片机的串行双工通信,要设置接收允许。

采用串行方式1,T1作为波特率发生器工作于方式2,取SMOD=0,T1的时间常数为E6。

发送部分程序采用查询式方法,先发送第一个字符,等待发送完毕后在发下一个,直字符串至全部发完。

实际发送中要用按键控制,当按键按下一次时,发送一次。

接收程序采用中断方式,当单片机接收到一个来自PC的字符时,产生串行口中断,将接受到的ASCII 码转换成单片机能够显示的字形码。

(3) 定时器部分:要求数码管显示器每隔1s交替显示“0123”和“4567”,很容易想到定时器控制。

选用定时器T0,工作方式1,16位计数,最大计数值65536,晶振为11.0592M,最大定时周期为71ms,不能满足要求,可以先定时50ms,此时计数初值为4C00,然后引入一个变量计数,每当定时器T0中断时变量加1,当计到20时刚好一秒,改变数码显示结果,再将计数变量清零,如此循环。

(4)液晶显示部分:用第一行接受来自PC端得字符,由于lcd1602一行只能显示16个字符,故要引入一个变量计数,每显示一个字符,计一次,计16次时表示屏幕显示满了,清屏。

第二行显示发送和接受的字符串,故要引入两个变量统计收发的字符数。

2.2电路图图2.1电路图图2.2 PC和单片机通信电路图图2.3 数码管交替显示2.3 流程图图2.4 程序流程图3程序代码本次设计的程序在keil上编写与调试,按照前面的设计思路采用分模块设计的方法,为每个模块建立一个文件,分别编写调试通过,然后在主函数中调用。

3.1主程序#include<reg52.h>#define uchar unsigned char#define uint unsigned intextern void int_rec(void) ;//中断接收extern void com_init(void); //串口初始化extern void sendstr(uchar *p);//字符串发送函数extern void display(uchar,uchar,uchar,uchar,uchar,uchar); //数码管显示函数extern void init(); //lcd初始化extern void write_com(uchar com); //lcd写命令extern void write_data(uchar date); //lcd写数据extern void timer0_init( ); //定时器初始化extern uchar dingshi(uchar n); //定时1s函数uint cnt_r=0,cnt_s=0;//发送接收计数uchar cnt_xs=0; //显示计数sbit key1=P3^7; //定义按键uchar a[6]={0,1,2,3,19,19};//数码管显示值uchar c[]={0xa0,0xa0,0xa0,0xa0,0};void num2char(uint temp) //无符号双字节数转为字符{c[4]=temp%10/1;//最低位c[3]=temp%100/10;c[2]=temp%1000/100;c[1]=temp%10000/1000;c[0]=temp%100000/10000;//最高位}void lcd_disp( ) //lcd显示函数{ uchar i;write_com(0x80+cnt_xs-1);//显示第一行if(cnt_xs>16) //第一行显示满后清屏{write_com(0x01);cnt_xs=1;}write_data(a[4]);num2char(cnt_s); //字符转换write_com(0x80+0x40);//显示第二行write_data('S'); write_data('E'); write_data(':');//显示字符串“SE:”for(i=0;i<5;i++)write_data(c[i]+0x30);//显示发送计数值num2char(cnt_r);//write_data('R'); write_data('E'); write_data(':');//显示字符串“RE:”for(i=0;i<5;i++) write_data(c[i]+0x30); //显示接收计数值}main() //主函数{uchar cnt=0; //通过计数,控制按一次键发送的次数com_init(); //串口初始化timer0_init(); //定时器初始化init();//lcd初始化while(1){if (key1==0) //按键按下时单片机发送字符串{ if(cnt<1){sendstr("HanBing");cnt++;}}else cnt=0; //按键弹起cnt清零display(a[0],a[1],a[2],a[3],19,a[5]); //6位数码管显示lcd_disp( ); //lcd显示if(dingshi(20)) //计到50次时即1s ,变换显示数字{a[0]=4-a[0];a[1]=6-a[1];a[2]=8-a[2];a[3]=10-a[3]; }}}3.2 串口通信程序#include <reg52.h>#define uchar unsigned char#define uint unsigned intextern uchar a[6]; //数码管6位extern void write_com(uchar com); //lcd写数据void do_uart(unsigned char charRcv); //串口接收执字符时的操作void sendchar(uchar uart_dat); //字符串发送extern uint cnt_r,cnt_s;//接收,发送计数extern uchar cnt_xs; //lcd显示计数/*串口发送字符串*/void sendstr(uchar *p){ while(*p!='\0'){ SBUF=*p; //待发送的数据写入缓冲区while(!TI); //等待发送完成TI=0; //清零发送标志位p++; //指针加1cnt_s++; //发送计数}}}void int_rec(void) interrupt 4 using 2 /*串口接收中断函数*/{ unsigned char Rcv = 0;if(RI) //查询接收标志位(有数据发送过来时置为1){RI = 0; //接收标志位清零Rcv = SBUF; //存储缓冲区的数据do_uart(Rcv);//对接受到得字符操作}}3.3数码管显示#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6; //段选信号sbit wela=P2^7; //位选信号uchar code table[]={ //共阴数码管表0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71, 0x76,0x73,0x38,0,0x40};//h p l 灭-void delay1(uint z) //延时子程序{uint t1,y;for(t1=z;t1>0;t1--)for(y=110/2;y>0;y--);}void display(uchar aa,uchar bb,uchar cc,uchar ba,uchar sh,uchar g) //用6个数码管显示{dula=1;P0=0;dula=0; //段初始化wela=1;P0=0xc0;wela=0;//位初始化dula=1;P0=table[aa];dula=0; //选中第一位P0=0xff;wela=1; P0=0xfe;wela=0;delay1(5);dula=1;P0=table[bb];point=0;dula=0;//选中第二位P0=0xff;wela=1;P0=0xfd; w ela=0;delay1(5);dula=1;P0=table[cc];dula=0;//选中第三位P0=0xff;wela=1; P0=0xfb;wela=0;delay1(5);dula=1;P0=table[ba];dula=0; //选中第四位P0=0xff;wela=1; P0=0xf7;wela=0;delay1(5);dula=1;P0=table[sh];dula=0; //选择第五位P0=0xff;wela=1;P0=0xef;wela=0;delay1(5);dula=1;P0=table[g];dula=0;//选择第六位P0=0xff;wela=1; P0=0xdf;wela=0;delay1(5);}3.4 定时程序#include<reg52.h>#define uchar unsigned charuchar t50ms=0; //50ms计数void timer0_init(void) //定时器初始化{TH0=0x4c;TL0=0; //定时器T0赋初值,晶振11.092M,定时50ms TR0=1; ET0=1;// 启动定时器T0}uchar dingshi(uchar n) //定时50ms的n倍{ if(t50ms>=n){t50ms=0; //50ms计数清零return 1;}return 0;}void timer0()interrupt 2 using 1//定时器T0产生50ms中断{t50ms++; //TH0=0x4c; //计数值重载TL0=0;}4 运行结果本设计采用的是Proteus仿真,电路图见前文,主意设置晶振为11.590M,串行全双工通信仿真采用的设备是虚拟终端,仿真前注意设置波特率为1200,数据位8位。