赞
踩
其中:
数据帧:每个字节的存放地,由起始位、数据位和停止位组成
数据位有8个代表一个字节的8位(还可能在最后有一个奇偶校验位)
波特率:串口通信的速率(两个设备协调的统一通信速率)
起始位:标志一个数据帧的开始,固定为低电平(空闲状态为高电平,起始位产生下降沿,来告诉设备要开始发送数据了)
停止位:用于数据帧间隔,固定为高电平(为下一个起始位做准备,切换到高电平空闲状态)
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
比如:发送一个字节为0x0F,首先转化为二进制0000 1111,再低位先行:依次传入1111 000,可将整个过程理解为蛇进洞
校验位:根据数据位计算得来,用于判断数据传输是否出错,出错可选择丢弃或者重传
奇校验:发送方发送数据后,包括校验位在内的9个数据位会出现奇数个1
原为0000 1111,则校验位补1,使1的个数为奇数
原为0000 1110,则校验位补0,使1的个数为偶数
接收方接收数据后,验证数据位和校验位中1的个数
偶校验类似(保证1个数为偶数)
CRC校验法(循环冗余校验码)(网上查过,看不懂一点。。。)
开端位->数据位->校验位->中止位
很少在该串口中使用同步功能,故基本上与UART差不多
同步功能多了一个时钟输出而已,甚至不支持时钟输入。。(不支持两个USART之间的同步通信)
可以看作为两部分:接受和发送
自带波特率发生器最高达4.5Mbits/s(最常用:9600,115200)
可配置数据位(8,常用/9)和停止位长度(0.5/1,常用/1.5/2)
可选校验位(无校验、常用/奇校验/偶校验)
持同步模式、硬件流控制(控制数据流量)、DMA、智能卡、IrDA(红外通信)、LIN(后三者属于其他协议)
stm32F103C8T6上共有3根USART的挂载线
发送器控制、接收器控制(顾名思义,很好理解)
硬件流控管脚:控制数据流流入速率(一般不用)
时钟引脚SCLK:产生同步的时钟信号,配合发送移位寄存器(一般不用)
发送寄存器每移位一次,同步时钟电平就跳变一个周期
唤醒单元:实现串口挂载多设备(一般不用)
在USART地址处给串口分配一个地址
当发送指定地址时此设备唤醒开始工作;
当发送别的设备地址时别的设备工作,没收到地址的设备不唤醒保持沉默
中断(输出)控制:TXE(发送寄存器空)和RXNE(接收寄存器非空)较重要
用于判断发送、接收状态的必要标志位
波特率发生器其实就是分频器
USART1挂载在APB2上(72MHz),其他的USART都挂载在APB1上(36MHz)
引脚模式 | USART1 | USART2 | USART3 |
---|---|---|---|
TX | PA9 | PA2 | PB10 |
RX | PA10 | PA3 | PB11 |
USART_DeInit(USARTx); //将USART寄存器重置为默认值 USART_Init(USARTx,&USART_InitStruct); //根据结构体的参数配置来对USARTx外设进行初始化 USART_StructInit(USART_InitStruct); //将USART_InitStructure结构体初始化 USART_ClockInit(USARTx, USART_ClockInitStruct) void USART_ClockStructInit(USART_ClockInitStruct) //用于时钟输出(不常用) USART_Cmd(USARTx, NewState) //使能或者失能USART外设 //eg:USART_Cmd(USART1 , ENABLE) USART_ITConfig(USARTx,USART_IT,NewState) //配置指定的USART中断 //eg:USART_ITConfig(USART1 , USART_IT_RXNE , ENABLE) USART_DMACmd(USARTx,USART_DMAReq, NewState) //使能或者失能USART的DMA请求 //eg:USART_DMACmd(USART1 , USART_DMAReq_Tx , ENABLE) USART_SendData(USARTx, uint16_t Data) //通过USARTx外设传输单个字节数据 uint16_t USART_ReceiveData(USARTx) //返回由USARTx外设接收的最新数据
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;//波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//流控
USART_InitStructure.USART_Mode = USART_Mode_Tx;//串口模式
USART_InitStructure.USART_Parity = USART_Parity_No;//校验位(ODD奇校验,EVEN偶校验)
USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
void Serial_SendByte(uint8_t Byte){
USART_SendData(USART1, Byte);
//将Byte变量写入TDR
//需要等待数据进入移位寄存器,所以需要等待一下标志位置1
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
//即等待发送数据寄存器空标志位变为SET(置1后)
//此时也不需要手动清零标志位,下一次SendData时会自动清零
}
(这里的发送案例是发送单个字节)
void Serial_SendArray(uint8_t Array[], uint16_t Length){
uint16_t i;
for (i = 0; i < Length ; i ++){
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char String[]){
uint8_t i;
for (i = 0; String[i] != 0;i++){
Serial_SendByte(String[i]);
}
}
void Serial_SendNumber(uint32_t Number,uint8_t Length){
uint8_t i;
for (i = 0 ; i < Length ; i++){
Serial_SendByte(Number / SerialPow(10,Length - i - 1) % 10 + '0');
}
}
int fputc(int ch, FILE *f){
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format, ...){
char String[100];
va_list arg;//定义一个参数列表变量
va_start(arg, format);//从format位置开始接受参数表,放在arg中
vsprintf(String, format, arg);//打印位置String,格式化字符串format,参数列表arg
va_end(arg);//释放参数表
Serial_SendString(String);//把String发送出去
}
void Serial_RecieveByte(uint8_t Byte){
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET){
Byte = USART_ReceiveData(USART1);
OLED_ShowHexNum(1, 1, Byte, 2);
}
}
(这里博主还没学,因为这个小项目暂时用不到)
关于python的串口通信可以参照 Python应用开发——串口通信
链接里有源码哦
串口发送
串口接收
剩下的就很简单啦,于是乎就有了:
特别声明:以上的图片部分来自于网络,感谢CSDN、知乎等平台上各位博主的分享,本文用作交流学习予以引用,在此一并表示感谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。