51单片机笔记[4]-串行口模块
作者:互联网
实验目的
- 熟悉Keil,Proteus软件的使用
- 熟悉串行口的编程、应用
实验内容
- 使用其他软件编写串口通信界面
- 使用串口调试助手。需要安装虚拟串口驱动(Virtual Serial Port Driver),并安装串口助手设置串口参数
完成双机通信实验
- 完成电路图绘制
- 通过甲机的按键,控制甲、乙两机的发光二极管点亮熄灭的状态
状态 |
---|
LED1亮,LED2亮 |
LED1亮,LED2灭 |
LED1灭,LED2亮 |
LED1灭,LED2灭 |
四种状态循环
- 通过乙机的按键控制甲机的八段数码管显示,内容为0-9
PC机与单片机通信
- 完成电路图绘制
- 通过JAVA或者其他软件编写控制串口程序,实现向单片机发送字符0-9,单片机通过数码管显示0-9
- 通过编写单片机程序,按下按键K1,向PC机发送本组学生的学号
原理
通信
单片机进行通信的常用方式:
- 蓝牙
- WIFI
- 串口
- IO口
数据传输方式
- 单工通信:数据传输仅能沿一个方向,不能实现反向传输
- 半双工通信:数据传输可以沿两个方向,但需要同时进行
- 全双工通信:数据同时进行双向传输
- 串行通信:使用一条数据线将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。
- 并行通信:将数据字节的各位用多条数据线同时进行传送,长距离传输抗干扰能力差
- 异步通信:通信的发送与接收设备使用各自的时钟控制数据的发送和接收。
- 同步通信:同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。
通信速率
- 比特率为每秒传输二进制代码的位数,单位:位/秒(bps),如每秒传输240字符,每个字符二进制格式为10位(1个起始,1个停止位,8个数据位),比特率为:10bit x 240 = 2400 bps
- 波特率为每秒传输码元的个数。码元常指时间间隔相同的符号表示二进制数字的信号,如0V表示0,5V表示1,一个码元可以表示0和1两种状态;如0V表示00,2V表示01,4V表示10,6V表示11,那么每个码元可以表示四种状态。
波特率的计算
串口工作方式 | 解释 | 波特率公式 |
---|---|---|
方式0 | 串行口为同步移位寄存器的输入输出方式 | $$ \frac{f_{osc}}{12} $$ |
方式1 | 10位数据异步通信 | $$ \frac{2^{SMOD}}{64}\dot f_{osc} $$ |
方式2 | 11位数据异步通信 | $$ \frac{2^{SMOD}}{32}\dot (\frac{f_{osc}}{12 \times (256-TH1)}) $$ |
方式3 | 11位数据异步通信 | $$ \frac{2^{SMOD}}{32}\dot (\frac{f_{osc}}{12 \times (256-TH1)}) $$ |
- 码率
理论上应该是按照编码方式无损传输,但现实没有这么美好。传输时需要加入一些用于纠错的信息码,用冗余换取高可靠度。码率就是排除纠错码之后实际真实传输的数据码占理论值的比例。
串口通信
串口通信最简系统需要包括TXD,RXD,SGND三个引脚.
接线:
发送方TXD接到接收方RXD,发送方RXD接到接收方TXD.
单片机一般只能处理TTL电平,而有时候串口会有其他方式来表示逻辑状态,如RS-232用正负电压来表示逻辑状态。
Keil显示中文乱码或者与其他软件中文编码不同
现在的代码编辑器(VScode)一般都是UTF8编码,如果直接复制网上的代码有可能会中文乱码,
Keil中,Configuration设置Encoding为UTF-8
配置stc15引脚为串口
一般51单片机都有P3.0和P3.1为串口,但是下载占用了这两个口,而stc15系列有4路串口,可以通过配置其他引脚来实现串口。
[https://www.cnblogs.com/hyydf/p/12593287.html]
本实验中使用P5.2/RXD4_2和P5.3/TXD4_2为串行口4
串行口4的相关寄存器
stc15引脚复用
51单片机的分时复用51单片机的分时复用功能,最直接的就是MOVX指令,用这个指令就是在分时复用P0口,执行:MOVX A,@DPTR,那么首先要送地址A0~A7给P0口,ALE有效,锁存在373上,再将这个地址的数据从P0口读入传给A。
下面是P0口既送数码管段信号,又送位信号的例子:
P0=table[a];//送段信号
duanLAH=1;
duanLAH=0;
P0=0xfe;//送位信号
weiLAH=1;
weiLAH=0;
实际上访问外部RAM时,P0口先送地址信号,ALE同时产生锁存信号,然后送数据信号,是不用程序人工干予的,这才是真正的分时复用
实验过程
原理图
串口实现双机通信 |
---|
流程图
串口通信-甲机 | 串口通信-乙机 | 串口与PC机通信 |
---|---|---|
代码
文件:23.c
//乙机串口接收
#include <stc15f2k60s2.h>
#define uchar unsigned char
#define uint unsigned int
sbit KEY2 = P3^3;
unsigned char distab[16] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//0-F
uint led_status_=0;
//延时
void delay(int ms){
int i,j;
for(i=0;i<ms;i++){
for(j=0;j<200;j++);
}
}
void ck_init_master(){
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x40;
PCON=0x00;
TR1=1;
}
uchar temp=0;
void key2_scan() interrupt 2{
if(KEY2==0){
delay(10);
if(KEY2==0){
P0=~distab[led_status_];
led_status_++;
if(led_status_==4) led_status_=0;
//同步数码管状态
ck_init_master();
}
}
}
void key_scan_init(){
//EX0=1;
EX1=1;
//IT0=1;
IT1=1;
EA=1;
}
void ck_init_slave(){
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x50;
PCON=0x00;
TR1=1;
}
void main()
{
key_scan_init();
while(1)
{
ck_init_slave();
while(RI==0);
RI=0;
temp=SBUF;
P4=temp;
temp=P0;
SBUF=temp;
while(TI==0);
TI=0;
}
}
文件22.c
//甲机串行发送
//#include <reg51.h>
#include <stc15f2k60s2.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1=P4^0;
sbit LED2=P4^1;
sbit KEY1=P3^2;
sbit KEY2=P3^3;
unsigned char distab[16] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//0-F
//延时
void delay(int ms){
int i,j;
for(i=0;i<ms;i++){
for(j=0;j<200;j++);
}
}
uchar led_status[]={0x3,0x01,0x02,0x0};//全亮,单亮
void key_scan_init(){
EX0=1;
EX1=1;
IT0=1;
IT1=1;
EA=1;
}
uint led_status_=0;
void key1_scan() interrupt 0{
if(KEY1==0){
delay(10);
if(KEY1==0){
P4=led_status[led_status_];
led_status_++;
if(led_status_==4) led_status_=0;
}
}
}
void ck_init_slave(){
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x50;
PCON=0x00;
TR1=1;
}
unsigned char temp=0;
void key2_scan() interrupt 2{
if(KEY2==0){
delay(10);
if(KEY2==0){
P0=~distab[2];
delay(1000);
//同步数码管状态
ck_init_slave();
while(RI==0);
RI=0;
temp=SBUF;
P0=temp;
}
}
}
void ck_init_master(){
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x40;
PCON=0x00;
TR1=1;
}
void main()
{
key_scan_init();
ck_init_slave();
while(1)
{
ck_init_master();
temp=P4;
SBUF=temp;
while(TI==0);
TI=0;
}
}
文件:20.c
//串口实现PC机与单片机通信
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
u8 xuehao[]={2,0,2,1,1,0,0,9,1,2,8};
sbit KEY=P3^1;
/*******************************************************************************
* 函 数 名 : uart_init
* 函数功能 : 串口通信中断配置函数,通过设置TH和TL即可确定定时时间
* 输 入 : baud:波特率对应的TH、TL装载值
* 输 出 : 无
*******************************************************************************/
void uart_init(u8 baud)
{
TMOD|=0X20; //设置计数器工作方式2
SCON=0X50; //设置为工作方式1
PCON=0X80; //波特率加倍
TH1=baud; //计数器初始值设置
TL1=baud;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口
//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void show_num(int input){
SMG_A_DP_PORT=gsmg_code[input];//将数组第input个数据赋值给数码管段选口
}
//串口4发送
void send(u8 _data){
int kk;
u8 sum;
do{
SBUF=_data;//SBUF»º´æ
while(!TI);//·¢ËÍÖжϱê־λ
TI=0;
while(!RI);//½ÓÊÜÖжϱê־λ
RI=0;
}
while(
(SBUF^0xbb)!=0 //SBUF²»ÎªÁãΪ0xbbʱ¾Í»áÖ´ÐÐÏÂÒ»ÌõÓï¾ä
);
//°´Î»·¢ËÍ
do{
sum=0;//sumΪУÑéºÍ£¬ÇåÁã
for(kk=0;kk<=7;kk++){
SBUF=_data;
sum+=_data;
while(!TI);
TI=0;//Èí¼þÇåÁã
}
SBUF=sum;//·¢ËÍУÑéºÍ
while(!RI);
RI=0;
}
while(
SBUF!=0
);//SBUFΪÁãÌø³öÑ»·
}
//按键扫描
void delay(int ms){
int i,j;
for(i=0;i<ms;i++){
for(j=0;j<200;j++);
}
}
void key_scan(){
if(KEY==0){
delay(10);
if(KEY==0){
int k;
for(k=0;k<11;k++){
send(xuehao[k]);
}
}
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
uart_init(0XFA);//波特率为9600
while(1)
{
show_num(5);
}
}
void uart() interrupt 4 //串口通信中断函数
{
u8 rec_data;
RI = 0; //清除接收中断标志位
rec_data=SBUF; //存储接收到的数据
show_num((int)rec_data);
SBUF=rec_data; //将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
delay(5000);
}
标签:P0,int,51,通信,串行口,unsigned,单片机,串口 来源: https://www.cnblogs.com/qsbye/p/16652868.html