USART串口通信
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USART串口通信相关的知识,希望对你有一定的参考价值。
一、同步通信
通信双方时钟一致。
typedef struct
uint16_t USART_Clock; // 时钟使能控制
uint16_t USART_CPOL; // 时钟极性
uint16_t USART_CPHA; // 时钟相位
uint16_t USART_LastBit; // 最尾位时钟脉冲
USART_ClockInitTypeDef;
二、异步通信
需要约定通信双方的的通信波特率。
void UART1Config( uint32_t bound)
USART_InitTypeDef USART_InitStructure;
//波特率设置
USART_InitStructure.USART_BaudRate = bound;
//字长为8位数据格式
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
//一个停止位
USART_InitStructure.USART_StopBits = USART_StopBits_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;
//初始化串口1
USART_Init(DEGUG_USARTX, &USART_InitStructure);
三、初始化串口
void UART1Init(void)
// 使能串口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
// 中断服务分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 中断嵌套
NVICInit(USART1_IRQn,0,0);
// PA9 USART1_TX
GPIOInit(USART1_TX_PORT,USART1_TX_PIN,GPIO_Mode_AF_PP);
// PA10 USART1_RX
GPIOInit(USART1_RX_PORT,USART1_RX_PIN,GPIO_Mode_IN_FLOATING);
// 波特率设置
UART1Config(115200);
USART_Cmd(USART1,ENABLE);
// 接收中断
USART_ITConfig(DEGUG_USARTX,USART_IT_RXNE,ENABLE);
// 发送中断
USART_ITConfig(DEGUG_USARTX,USART_IT_TXE,ENABLE);
四、中断配置
void NVICInit(uint8_t IRQChannel,uint8_t IRQC_PTP,uint8_t IRQC_SP)
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
// 中断通道
NVIC_InitStructure.NVIC_IRQChannel = IRQChannel;
// 抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQC_PTP;
// 响应式优先级/副优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = IRQC_SP;
// 使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*
外部中断
EXTI 的每根输入线都可单独进行配置,以选择类型(中 断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)
EXTI线路 说明
EXTI线0~15 对应外部IO口的输入中断
EXTI线 16 连接到PVD输出
EXTI线17 连接到RTC闹钟事件
EXTI线18 连接到USB OTG FS唤醒事件
EXTI线19 连接到以太网唤醒事件
每个 GPIO 端口均有 16 个管脚,每个 端口的 16 个 IO 对应那 16 根中断线 EXTI0-EXTI15。
*/
/*
Function:外部中断
*/
void EXTIInit(uint8_t GPIO_PORT, uint8_t GPIO_Pin,uint32_t EXTILine,EXTIMode_TypeDef Mode, EXTITrigger_TypeDef EXTI_Trigger)
EXTI_InitTypeDef EXTI_InitStructure;
// 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
// 外部中断的端口 与引脚
GPIO_EXTILineConfig(GPIO_PORT, GPIO_Pin);
EXTI_InitStructure.EXTI_Line =EXTILine; // 中断/事件线
EXTI_InitStructure.EXTI_Mode = Mode; // EXTI 模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger; // EXTI 触发方式
EXTI_InitStructure.EXTI_LineCmd =ENABLE; // 中断线使能或失能
EXTI_Init(&EXTI_InitStructure);
五、GPIO配置
void GPIOInit(uint32_t RCC_APB2Periph,GPIO_TypeDef* GPIOx,uint16_t GPIOPin,uint16_t GPIOMode)
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIOPin;
GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)GPIOMode;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOx,&GPIO_InitStructure);
APB2上的时钟可选:
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
六、中断服务函数
6.1、方式一
void DEBUG_USART_IRQHandler(void)
uint8_t ucTemp;
if (USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
ucTemp = USART_ReceiveData( USART1);
USART_SendData(USART1,ucTemp);
/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
/* 发送一个字节数据到 USART */
USART_SendData(USART1,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
unsigned int k=0;
do
Usart_SendByte( USART1, *(str + k) );
k++;
while (*(str + k)!='\\0');
/* 等待发送完成 */
while (USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)
int main(void)
/*初始化 USART 配置模式为 115200 8-N-1,中断接收*/
USART1Init();
/* 发送一个字符串 */
Usart_SendString( USART1,"这是一个串口中断接收回显实验\\n");
while (1)
6.2、方式二
接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART1_RX_STA=0;
void USART1_IRQHandler(void) //串口1中断服务程序
u8 r;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if((USART1_RX_STA&0x8000)==0)//接收未完成
if(USART1_RX_STA&0x4000)//接收到了0x0d
if(r!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
else USART1_RX_STA|=0x8000; //接收完成了
else //还没收到0X0D
if(r==0x0d)USART1_RX_STA|=0x4000;
else
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r;
USART1_RX_STA++;
if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
int fputc(int ch,FILE*p)
// Transmits single data through the USARTx peripheral.
// 通过USARTx外围设备传输单个数据。
USART_SendData(USART1,(u8)ch);
// Checks whether the specified USART flag is set or not.
// 检查是否设置USART指定的标志
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==!RESET);
return ch;
void USART1_MAIN_Logic(void)
接收到数据
if(USART1_RX_STA&0x8000)
//得到此次接收到的数据长度
len=USART1_RX_STA&0x3fff;
for(t=0;t<len;t++)
USART_SendData(USART1, USART1_RX_BUF[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
USART1_RX_STA=0;
以上是关于USART串口通信的主要内容,如果未能解决你的问题,请参考以下文章