身价过亿的妖媚子对小码农说串口能传送我的爱吗?
Posted 小码农U
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了身价过亿的妖媚子对小码农说串口能传送我的爱吗?相关的知识,希望对你有一定的参考价值。
文章目录
小码农不敢接受妖媚子(想多活几年),但是串口还是可以传送数据的
并行通信
多位数据同时传输
通讯介质通常为TTL,差分(低压差分芯片)
例如:LCO1602,ADC0804,LVDS(液晶显示)等
串行通信
多位数据排队传输,任意IO口都可以做数据收发
通信介质通常为TTL,差分(485),无线电
同步:
74HC595(单工),IIC(半双工),SPI
异步:
单线归零、1- Wire 、 CAN 总线、无线电、UART (含 DMX512 、 modbus )。
UART 是单片机的独立模块。我们设置好模块的参数,需要发送什么内容,扔给串口模块就行。 CPU 不需要按位读写。该模块是指定的管脚输入输出。目前, STC 所有型号串口1 的输入是 RxD1=P3.0, , 输出是 TxD1=P3.1 。
STC15 开发板使用 STC15W4K16S4 芯片,串口有4个,其中串口3的输入是 RxD3= P0.0, , 输出是 TxD3= P0.1 。与矩阵键盘共用了两个 IO
串口通信:收发一个字节(只能用时间来同步)
CPU 往 SBUF 中写入一个 byte , CPU 可以跑去执行其他函数。如果发送完成,串口模块向 CPU 申请中断(T1);
串口收发一位数据,依靠严格的时间来保证收发同步
如果串口模块接收完一个字节,也向 CPU 申请中断( RI ),CPU 可以从 SBUF 中读取数据。
串口通讯的相关术语
**1.位采样脉冲:**接收器把每个 bit 的时间平均等份,对线路电平进行采样,确定接收到的是高电平还是低电平,才能进行下一位数据的采样。 STC89 是 16 等份判断7、8 、9(三选二)。STC15W 和 STC8 系列是4等份(四选三,官方资料写错成 16 了)
2.波特率:: 是指1秒钟的时间内,串口通信线路上面,发送的数据位数, , 简单理解成1秒钟内电平跳变多少次
常用的波特率有 9600 等, STC 下载软件里面可以选择的就有很多种波特率。我们后面要学的 DMX512 就是 250000bps .
**波特率的本质,是设置信号时间点。**到点就按时发送或者接收一位。串口全双工通信是没有时钟脉冲的,只能依靠晶振脉冲、定时器的溢出脉冲。
==3.波特率哪里来:==波特率来自定时器的溢出,独立波特率发生器,以及系统时钟分频
STC串口1通信的寄存器
1.方式设置以及中断标志寄存器
2.电源控制寄存器中的波特率加倍功能寄存器
3.数据收发缓存寄存器SBUF
4.辅助寄存器AUXR控制定时器分频,独立波特率发3生器以及串口2的相关控制
5.独立波特率发生器寄存器BRT,用于保存该定时器的初值
6.与串口通信相关的中断寄存器IE,中断优先级IPH,IP
串行口1工作模式1:8位UART,波特率可变
收发波特率需要一致
收发波特率不一致,导致RX端不能正常接收:
串口1
1.配置 SCON ,选择方式1,8 位可变波特率,允许接收。
SM0 = 0;SM1 = 1;REN = 1;
PCON &= 0x3f;
2.配置定时器2为 :16 位自动重装模式, 不申请中断 AUXR |= 0x01;AUXR |= 0x14; 实际上也可以写成AUXR |= 0x15;
3.计算定时器2的溢出率:
波特率是 9600 ,每位采样4次。就需要定时器2每秒钟溢出 9600*4 次 =38400
4.配置定时器2初值
定时器2溢出需要的脉冲数是:24000000 ÷ 38400=625. 那么,定时器2的预装初值就是:65536-625=64911=0xFD8F
5.启动定时器2、闭合串口1中断开关、闭合总中断开关。ES = 1
6.中断中读取SBUF,清 RI 标志,然后返回给计算机,等待发送完毕,防重叠最少时间=4 次*10 位* 定时器时间 。再清除 TI
void Uart1_Init()
SM0 = 0;
SM1 = 1;
REN = 1;
//上面三条语句就等于操作SCON |= 0x50;
PCON &= 0x3f;
AUXR |= 0x01;
AUXR |= 0x14;
T2H = 0xfd;
T2L = 0x8f;
ES = 1;
串口1中断函数
串口1中断号
在中断里面我们干什么,进中断第一件事就是先把接收标志,发送标志给软件清零,然后再做一系列操作
void Uart1_Routine() interrupt 4
if (RI)
RI = 0;//先把接收标志给清零
Uart1_Data = SBUF;
if (TI)
TI = 0;//先把发送标志给清零
串口中断让单片机软复位,实现自动烧录 IAP_CONTR |= 0xe0
监控串口通信内容,如果在 9600 波特率下,连续收到 10 个字节都是 0x7f, 那么让单片机软复位,去支持 ISP 监控区域代码。实现烧录程序的目的。单片机不断电就可下载程序,方便项目调试
上面我们故意用最低波特率与最高波特率都是1200,小于9600,我就点了下载,(板子是上电的)没有用板子的开关复位,就是通过纯软件复位,等了几秒没有反应,说明我们用9600下载的方式是不支持1200下载的
9600很慢的(哈哈)下载了
我们发现只要最低波特率到9600就可以软复位了,越高会下载越快
void Uart1_Routine() interrupt 4
//记录接收命令流变量
static char Uart1_ser_n = 0;
if (RI)
RI = 0;//先把接收标志给清零
Uart1_Data = SBUF;
if (SBUF == 0x7f) //9600波特率
//接收命令为0x7f时就++
Uart1_ser_n++;
if(Uart1_ser_n > 10)//大于10基本就是确定是下载命令
Uart1_ser_n = 0;
//然后执行软复位
IAP_CONTR |= 0xe0;
if (TI)
TI = 0;//先把发送标志给清零
上面是发送一个字节,现在我们发送字符串
先了解一下SBUF
为什么一直是0xFF,眼看也不是1啊是不是 ,我们用逻辑分析仪来抓取看看
延时后
完美,为了让你直观的看到美,我采集一下给你们看看
我们调整上一个字节发送完成后马上发送下一个字节
我们给他一个标志位,前面一个字节发送完成后,标志位修改,然后发第二个字节,以此类推
//串口发送底层驱动的函数
void Uart1_Up_Data_Drive()
//串口1标志为1才能发送字节,
//可以让数据有效的发送
if(Uart1_Flag)
Uart1_Flag = 0;
SBUF = 1;
//串口1中断
void Uart1_Routine() interrupt 4
//记录接收命令流变量
static char Uart1_ser_n = 0;
if (RI)
RI = 0;//先把接收标志给清零
if (SBUF == 0x7f) //9600波特率
//接收命令为0x7f时就++
Uart1_ser_n++;
if(Uart1_ser_n > 10)//大于10基本就是确定是下载命令
Uart1_ser_n = 0;
//然后执行软复位
IAP_CONTR |= 0xe0;
if (TI)
TI = 0;//先把发送标志给清零
//数据全部发送完成后标志位置1
//置1后是准备发送后一个字节
Uart1_Flag = 1;
//调用串口发送函数
Uart1_Up_Data_Drive();
发字符串
单片机没有数据接收,串口标志就不会置1,电压就发不出去
我们可以看到接收缓冲区啥也没有,那就是因为发送缓冲区没有数据发送,单片机也就没有数据接收,标志没置1,然后单片机发送数据就没有一个触发的引子
单片机有数据接收,串口标志就会置1,电压就发出去
我们发送任意数据都可以,只要单片机接收到数据就行,然后串口标志就会置1,使得串口发送函数有用,我们就可以看到电压显示出来,但是细心的同学会发现,我的发送汉字缓冲区明明是换行回车,你这也没看到啊,那是SPI软件有点小毛病,我们换个软件
发送汉字缓冲区有 \\n\\r换行回车
发送汉字缓冲区有 \\n换行,无回车
发送汉字缓冲区无换行,有回车\\r
发送汉字缓冲区无换行,无回车
所以知道为什么我在发送汉字缓冲区中写换行回车了吗
主要代码
Uart1_Drive.c
#include "all.h"
//需要显示串口的临时变量
bit Uart1_Flag = 1;
//汉字是固定的 直接code
//串口发送汉字数组缓存 先换行\\n回车\\r
u8 code Uart1_Up_Symbol_Buffer[30] = "\\n\\r电压: ";
//串口发送数字数组缓存 20个足够以后用的了
u8 xdata Uart1_Up_Num_Buffer[20];
//串口1初始化
void Uart1_Init()
SM0 = 0;
SM1 = 1;
REN = 1;
//上面三条语句就等于操作SCON |= 0x50;
PCON &= 0x3f;
AUXR |= 0x01;
AUXR |= 0x14;
T2H = 0xfd;
T2L = 0x8f;
ES = 1;
//串口发送底层驱动的函数
void Uart1_Up_Data_Drive()
static xdata u8 count = 0;
//串口1标志为1才能发送字节,
//可以让数据有效的发送
if(Uart1_Flag)
Uart1_Flag = 0;
count++;
switch (count)
case 1: SBUF = Uart1_Up_Symbol_Buffer[0];break;
case 2: SBUF = Uart1_Up_Symbol_Buffer[1];break;
case 3: SBUF = Uart1_Up_Symbol_Buffer[2];break;
case 4: SBUF = Uart1_Up_Symbol_Buffer[3];break;
case 5: SBUF = Uart1_Up_Symbol_Buffer[4];break;
case 6: SBUF = Uart1_Up_Symbol_Buffer[5];break;
case 7: SBUF = Uart1_Up_Symbol_Buffer[6];break;
case 8: SBUF = Uart1_Up_Symbol_Buffer[7];break;
case 9: SBUF = Uart1_Up_Symbol_Buffer[8];break;
case 10:SBUF = Uart1_Up_Symbol_Buffer[9];break;
case 12:SBUF = Uart1_Up_Num_Buffer[0];break;
case 14:SBUF = Uart1_Up_Num_Buffer[1];break;
case 16:SBUF = Uart1_Up_Num_Buffer[2];break;
case 18:SBUF = Uart1_Up_Num_Buffer[3];break;
case 20:SBUF = Uart1_Up_Num_Buffer[4];break;
case 22:SBUF = Uart1_Up_Num_Buffer[5];break;
case 24:count=0;break;
//串口1中断
void Uart1_Routine() interrupt 4
//记录接收命令流变量
static char Uart1_ser_n = 0;
if (RI)
RI = 0;//先把接收标志给清零
//当接收到一个字节时,串口标志置1
Uart1_Flag = 1;
if (SBUF == 0x7f) //9600波特率
//接收命令为0x7f时就++
Uart1_ser_n++;
if(Uart1_ser_n > 10)//大于10基本就是确定是下载命令
Uart1_ser_n = 0;
//然后执行软复位
IAP_CONTR |= 0xe0;
if (TI)
TI = 0;//先把发送标志给清零
//数据全部发送完成后标志位置1
//置1后是准备发送后一个字节
Uart1_Flag = 1;
//调用串口发送函数
Uart1_Up_Data_Drive();
Uart_Drive.h
#ifndef Uart1_Drive
#define Uart1_Drive
//外部声明
extern void Uart1_Init();
extern bit Uart1_Flag;
extern void Uart1_Up_Data_Drive();
extern u8 xdata Uart1_Up_Num_Buffer[20];
#endif
以上是关于身价过亿的妖媚子对小码农说串口能传送我的爱吗?的主要内容,如果未能解决你的问题,请参考以下文章