ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

51单片机笔记[4]-串行口模块

2022-09-09 20:02:28  阅读:154  来源: 互联网

标签:P0 int 51 通信 串行口 unsigned 单片机 串口


实验目的

  1. 熟悉Keil,Proteus软件的使用
  2. 熟悉串行口的编程、应用

实验内容

  1. 使用其他软件编写串口通信界面
  2. 使用串口调试助手。需要安装虚拟串口驱动(Virtual Serial Port Driver),并安装串口助手设置串口参数

完成双机通信实验

  1. 完成电路图绘制
  2. 通过甲机的按键,控制甲、乙两机的发光二极管点亮熄灭的状态
状态
LED1亮,LED2亮
LED1亮,LED2灭
LED1灭,LED2亮
LED1灭,LED2灭

四种状态循环

  1. 通过乙机的按键控制甲机的八段数码管显示,内容为0-9

PC机与单片机通信

  1. 完成电路图绘制
  2. 通过JAVA或者其他软件编写控制串口程序,实现向单片机发送字符0-9,单片机通过数码管显示0-9
  3. 通过编写单片机程序,按下按键K1,向PC机发送本组学生的学号

原理

通信

单片机进行通信的常用方式:

  • 蓝牙
  • WIFI
  • 串口
  • IO口

数据传输方式

  • 单工通信:数据传输仅能沿一个方向,不能实现反向传输
  • 半双工通信:数据传输可以沿两个方向,但需要同时进行
  • 全双工通信:数据同时进行双向传输

  • 串行通信:使用一条数据线将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。
  • 并行通信:将数据字节的各位用多条数据线同时进行传送,长距离传输抗干扰能力差

  • 异步通信:通信的发送与接收设备使用各自的时钟控制数据的发送和接收。
  • 同步通信:同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。

通信速率

  1. 比特率为每秒传输二进制代码的位数,单位:位/秒(bps),如每秒传输240字符,每个字符二进制格式为10位(1个起始,1个停止位,8个数据位),比特率为:10bit x 240 = 2400 bps
  2. 波特率为每秒传输码元的个数。码元常指时间间隔相同的符号表示二进制数字的信号,如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)}) $$
  1. 码率
    理论上应该是按照编码方式无损传输,但现实没有这么美好。传输时需要加入一些用于纠错的信息码,用冗余换取高可靠度。码率就是排除纠错码之后实际真实传输的数据码占理论值的比例。

串口通信

串口通信最简系统需要包括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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有