下面是9针串口的各个引脚
串口通信时序图
一组数据是由起始位+数据位+奇偶校验位+停止位组成。
起始位
下降沿信号触发,表示数据开始传输。
数据位
有5~8位,一般采用8位,因为我们平时传输的英文字符,是使用8bit的字节来进行ascall码表示的。
奇偶校验位
如果数据中的“1”的总数为奇数个,那么就是奇校验。
如果数据中的“1”的总数为偶数个,那么就是偶校验。
停止位
一般有1、1.5、2位表示,一般使用1位。
源码
以stm32f103c8t6为例
实际上是利用USART_SendData()这个函数进行按字节发送。和USART_GetITStatus()函数判断接收中断位是否发生改变来进行接收数据。
uart.c
#include "uart.h"
void uart_config(void)
{
/* GPIO端口设置 */
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
/* PA2 TXD2 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PA3 RXD2 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Usart2 NVIC 配置 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 嵌套向量中断控制器组选择 2位抢占 2位响应*/
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; /* 抢占优先级3 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; /* 响应优先级2 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* IRQ通道使能 */
NVIC_Init( &NVIC_InitStructure ); /* 根据指定的参数初始化NVIC寄存器 */
/* USART 初始化设置 */
USART_InitStructure.USART_BaudRate = 115200; //设置波特率;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
USART_Init(USART2, &USART_InitStructure);
/* 开启中断 */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启接收中断
//USART_ClearFlag(USART2,USART_FLAG_TC);
USART_Cmd(USART2, ENABLE);//使能串口
}
void usart2_send_byte(u8 data)
{
while(!USART_GetFlagStatus(USART2,USART_FLAG_TXE)){}
USART_SendData(USART2,data);
}
void USART2_IRQHandler(void)
{
u8 res=0;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
//led_turn();
res = USART_ReceiveData( USART2 );
//USART_SendData(USART2,res);
}
}
51单片机
实际上是将数据放入SBUF中,然后等待TI状态位改变,进行发送。判断RI状态位是否改变来获取数据输入。
#include <reg52.h>
#include "uart.h"
#define uint unsigned int
#define uchar unsigned char
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
//串口初始化函数 9600
void URATinit()
{
TMOD=0x20;
SCON=0x50;
TR1=1;
TH1=0xfd;
TL1=0xfd;
EA=1;
ES=1;
}
//发送一个字符
void Uart_Send_Byte(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI=0;
}
u8 ch,i;
u8 RX_BUF[10],RX_DAT[10],RX_CNT=0,RX_OVER=0;
//串口接收中断
void Uart_IRQ() interrupt 4
{
/*if(RI)
{
RI=0;//清标志位
ch=SBUF;
if(ch=='A') {}
} */
if(RI)
{
ch=SBUF;
if(ch!='}')
{
RX_BUF[RX_CNT++]=ch;
}
else //结束
{
for(i=0;i<RX_CNT;i++)
{
RX_DAT[i]=RX_BUF[i];
}
RX_CNT=0;
RX_OVER=1;
}
RI=0;//清标志位
}
}
//重写putchar函数
char putchar(char c)
{
Uart_Send_Byte(c);
return c;
}
RS232与RS485的区别
1)RS232
对于TTL电平:3.3V或者5V为高电平,0V为低电平。这样的缺点就是容易失真,也导致了采用TTL电平的普通串口的有效传输距离不远。
RS232电平:3V-15V为高电平-15V-3V为低电平。为全双工通信模式。
(2)RS485
RS485为一般半双工通信模式(也可全双工),使用差分信号。
RS485差分线路包括2个信号:
线路A(TX+/RX+、D+):非方向信号
线路B(TX-/RX-、D-):反向信号
表示0和1:
若是SPACE(逻辑0),线路A信号电压比线路B高
若是MARK(逻辑1),线路B电压比线路A高
当一个总线上需要多个主机/从机时,使用RS485更合适,一般用于自动化工厂。