目录
#串口通信#
①通信基础知识
信息交换
可以同时进行的信息交换(说跟听可以同时进行)——全双工串口通信
只有其中一个可以进行信息交换(说跟听只有一个可以进行)——半双工串口通信
只有一个信道通信(一一对应的信息交换,只有一个嘴巴一个耳朵)——串行通信
有很多信道通信(有很多嘴巴很多耳朵)——并行通信
可以自己适应语速但有bug——异步通信

波特率:一秒传输多少位
比特率:一秒发多少字节
数据格式:起始位+八个数据位+奇偶校验位+停止位
上下位机通信
上下位机通信设置
补充知识点
②代码思路
先配SCOM:SM0和SM1置01;REN=1;TI和RI置0;再配AUXR:选择定时器2为波特率发生器,并为1T:装初值TH2和TL2;最后ES=1和EA=1
③代码注意点:
①TXD与RXD连接
②通信速率确定——单片机中定时器决定

串口1一般是定时器2为波特率发生器来计时
定时器溢出一次的时间就是串口发一次数据时间t1
波特率设为x
④串口程序设计
1.初始工作
在模块里添加SYS文件夹中UART文件夹(与sys和delay统一等级)
新建俩个文件uart.c和uart.h
在魔法棒里,C51添加文件路径
再将文件添加到工程中
2.代码参考
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; //使能串口1中断
}
//EA在主函数打开
代码源头可查找ISP
在主函数定义发送数组
发送函数编写
void Uart_send(uchar *Str)
{
while(++Str !="\0")
{
SBUF = *Str;//发送数组内容
while(TI==0);//发送完成TI=1
TI=0;
Str++;
}
}
在串口接收数据之前要加一个中断服务函数,因为串口接收是通过触发中断实现的
若接收数据完成,会触发中断服务函数
void Uart1_Isr(void) interrupt 4
{
if (RI) //检测串口1接收中断
//RI=1,说明数据接收完成,响应中断后,RI=0清零
{
Uart_buf[++index]=SBUF;//将SBUF内容给数组
RI = 0; //清除串口1接收中断请求位
}
}
主函数代码编写
将“你好”转换到Uart_Txbuf中
这种写法有缺点,每次打印东西,都要将内容赋值到数组中
数组定义很大,就浪费空间
3.运行代码
1.点击运行
2.串口助手,清空接收区,串口com与STC保持一致,波特率与文件内容保持一致,打开串口
优化代码
用printf来打印内容,用putchar来引用,#include<studio.h>
接收函数编写
char putchar(char ch)
{
SBUF=ch;
while(TI==0);//等待发送完成
TI=0;//发送完成标志位置0
return ch;
}
void main()
{
Uart1_Init();
EA=1;
printf("Distance: %ucm",2025);//因为有putchar函数,所以可以直接使用printf函数
}
注意printf函数在keil中的使用
⑤数据接收信号并文字显示(竞赛内容)
14届模拟题二(有关串口内容成功显示)
uart.c编写
#include "uart.h"
//若串口接收,就需要增加中断
void Uart1_Isr(void) interrupt 4
{
if (RI) //检测串口1接收中断
{
uart_flag=1;//接受标志位
uart_systick=0;//接收时间置零
rec_buf[index++]=SBUF;
RI = 0; //清除串口1接收中断请求位
if(index>2)index=0;//接收信号0 1
}
}
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xC7; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
EA=1;
}
char putchar(char ch)
{
SBUF=ch;
while(TI==0);
TI=0;
return ch;
}
uart.h编写
#ifndef __UART_H_
#define __UART_H_
#include "sys.h"
void Uart1_Init(void); //9600bps@12.000MHz
char putchar(char ch);
extern uchar rec_buf[5];
extern uchar index;
extern uchar uart_systick;
extern bit uart_flag;
#endif
main.c编写(串口有关内容)
bit flag_send;//每次发送当前数码管显示数据
uchar uart_systick;//接收数据的时间
bit uart_flag;//接收数据标志位,0未接收 1接收
//if(uart_flag==1) uart_stick++;
void Timer0_Isr(void) interrupt 1
{
//***********************
if(uart_flag==1)uart_systick++;//接收数据后,开始计时
//**************************
}
void collect()
{
if(collect_dly<500)return;
collect_dly=0;
temp=temperature(1);//3位onewire温度
Vol=(read_ADDA(0x03)/51.0)*100;//电压显示
//////////////////////////////////////////////////////////
if(flag_send==1)//S12按下发送数据
{
if(state_display==0)//温度显示界面
{
printf("TEMP:%.1f℃",temp/10.0);
}//1位小数点,温度位三位数
else if(state_display==1)
{
printf("Voltage:%.2fV",Vol/100.0);
} //2位小数
flag_send=0;//停止发送数据
}
}
///////////////////////////////////////////////////////
void uart_pro()
{
if(index==0)return;//接收信号的帧头,失败
if(uart_systick>=10)//接收信号超过十毫秒
{
uart_flag=uart_systick=0;//时间重置,标志位置零,接收成功
if(index>0)//接收到帧头,并且由连续接受下去的趋势
{
if(index==1)//接收到信号
{
if(rec_buf[0]=="A"&&uart_state==1)//接收到信号并且是在解锁界面
{
state_display=0;
display();
}
else if(rec_buf[0]=='B'&&uart_state==1)
{
state_display=1;//电压显示界面
display();
}
}
}
index=0;//接收完数据,重新读取信号
}
}