SR能避免莫名其妙的错误 u8 USART1_RX。STM32 UART常用的3种中断接收。" />

STM32 UART常用的3种中断接收

#include "sys.h"
#include "usart.h"
#include "main.h"


//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h" //ucos 使用
#endif




//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART1_RX_BUF[USART_RX_LEN]; //接收缓冲,最USART_RX_LEN个字节
u8 USART2_RX_BUF[USART_RX_LEN]; //接收缓冲,最USART_RX_LEN个字节
u8 USART1_TX_BUF[USART_TX_LEN]; //发送缓冲,最大USART_TX_LEN个字节
u8 USART2_TX_BUF[USART_TX_LEN]; //发送缓冲,最大USART_TX_LEN个字节
u8 USART1_RX_STA; //接收完成状态标记
u8 USART2_RX_STA; //接收完成状态标记
u8 USART3_RX_STA; //接收完成状态标记
//u8 USART1_Count = 0; //USART1接收计数器
//u8 USART2_Count = 0; //USART2接收计数器
u8 TX1_cn,TX1_no,RX1_cn,RX_no;
u8 TX2_cn,TX2_no,RX2_cn,RX2_no;
u8 u8Uart2_FSM;


void usart1_init(u32 baud)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;


/* 第1步:打开GPIO和USART部件的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


/* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);


/* 第3步:将USART Rx的GPIO配置为浮空输入模式
由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*第3步已经做了,因此这步可以不做
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第4步:配置USART参数
- 波特率= 115200 baud
- 数据长度 = 8 Bits
- 1个停止位
- 无校验
- 禁止硬件流控(即禁止RTS和CTS)
- 使能接收和发送
*/
USART_InitStructure.USART_BaudRate = baud;
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;
USART_Init(USART1, &USART_InitStructure);
////Usart1 NVIC 配置
//NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ; //抢占优先级1
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
// NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断
/* 第5步:使能 USART, 配置完毕 */
USART_Cmd(USART1, ENABLE);
// CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
// 如下语句解决第1个字节无法正确发送出去的问题:
// 清发送完成标志,Transmission Complete flag
USART_ClearFlag(USART1, USART_FLAG_TC);
}




/*************************************************************************************************************************
* 函数 : void uart2_init(u32 baud)
* 功能 : USART2做RS485接口使用,
* 参数 : 输入的波特率
* 返回 : 无
* 依赖 : 底层库函数
* 作者 : li_qcxy@126.com
* 时间 : 2016-12-9
* 最后修改时间 :
* 说明 : PA1为接收发送使能脚
*************************************************************************************************************************/
void usart2_init(u32 baud)//485通信串口初始化
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART2,GPIOA时钟

//USART2_TXGPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.2

//USART2_RX GPIOA.3初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.3

//USART2_RX_EN 使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PA1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA1
EN_USART2_RX(); //接收模式

//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

//USART 初始化设置
USART_InitStructure.USART_BaudRate = baud; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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; //收发模式


USART_Init(USART2, &USART_InitStructure); //初始化串口2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(USART2, ENABLE); //使能串口2
USART2 -> CR1 = USART2 -> CR1;
}






//获取USART2当前接收计数器值
u32 UARTx_GetRxCnt(void)
{
return TX2_no;
}


/*************************************************************************************************************************
* 函数 : void USART1_IRQHandler(void)
* 功能 : 采用缓冲区满标志位的方法判断数据接收完成
* 参数 : 无
* 返回 : 无
* 依赖 : 底层读写函数
* 作者 : li_qcxy@126.com
* 时间 : 2016-12-8
* 最后修改时间 :
* 说明 :
*************************************************************************************************************************/
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
USART1_RX_BUF[TX2_no++]=Res;
}
else if(TX2_no == USART_RX_LEN) //接收缓冲区接收满,即接收完成
{
TX2_no = 0;
USART1_RX_STA = 1;
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
/*************************************************************************************************************************
* 函数 : void USART2_IRQHandler(void)
* 功能 : 采用空闲中断的方法判断数据接收完成
* 参数 : 无
* 返回 : 无
* 依赖 : 底层读写函数
* 作者 : li_qcxy@126.com
* 时间 : 2016-12-8
* 最后修改时间 :
* 说明 :
*************************************************************************************************************************/
void USART3_IRQHandler(void) //串口2中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART2); //(USART2->DR); //读取接收到的数据
USART2_RX_BUF[TX2_no++]=Res;
}
else if((USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)) //使用空闲中断判断接收不定长数据完成
{
USART3_RX_STA = 1; //数据接收完成标志位
//
}
}


/*************************************************************************************************************************
* 函数 : void USART2_IRQHandler(void)
* 功能 : 采用状态机的方法判断数据接收完成
* 参数 : 无
* 返回 : 无
* 依赖 : 底层读写函数
* 作者 : li_qcxy@126.com
* 时间 : 2016-12-8
* 最后修改时间 :
* 说明 :
*************************************************************************************************************************/
void USART2_IRQHandler(void)
{
u8 u8Temp;
/*****************发送中断************************************/
if (USART_GetITStatus(USART2, USART_IT_TC) == SET)
{
if(TX2_cn >= (TX2_no))
{
EN_USART2_TX();
USART_ITConfig(USART2, USART_IT_TC, DISABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
u8Uart2_FSM = U_FSM_ADR;
}
else
{
u8Temp = USART2_TX_BUF[TX2_cn++];
USART2->DR = (u16)u8Temp;
}
}

/******************接收中断*************************************/
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
u8Temp = (u8)USART2->DR;
switch(u8Uart2_FSM)
{
case U_FSM_ADR:
{
if(u8Temp == local_info.id)//本地地址
{
USART2_RX_BUF[0] = u8Temp;
u8Uart2_FSM = U_FSM_FUN;
}
break;
}
case U_FSM_FUN:
{
if((u8Temp == 0x05)||(u8Temp == 0x01)||(u8Temp == 0x03)||(u8Temp == 0x04)) //本单元值接受0x05和0x01的指令,遥信和遥控
{
USART2_RX_BUF[1] = u8Temp;
u8Uart2_FSM = U_FSM_DATA;
RX2_no = 8;
RX2_cn = 2;
}
else if(u8Temp == 0x10)
{
USART2_RX_BUF[1] = u8Temp;
u8Uart2_FSM = U_FSM_FUN16;
//RX2_no = 15;
RX2_cn = 2;
}
else
{
u8Uart2_FSM = U_FSM_ADR;
}
break;
}
case U_FSM_FUN16:
{
USART2_RX_BUF[RX2_cn++] = u8Temp;
if(RX2_cn == 6)
{
USART2_RX_BUF[6] = u8Temp;
u8Uart2_FSM = U_FSM_DATA16;
RX2_cn = 7;
RX2_no = 9 + USART2_RX_BUF[6];
}
// else
// {
// USART2_RX_BUF[RX2_cn++] = u8Temp;
// }
break;
}
case U_FSM_DATA:
{
USART2_RX_BUF[RX2_cn++] = u8Temp;
if(RX2_no <= RX2_cn)//数据接收完毕
{
u8Uart2_FSM = U_FSM_ADR;
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //一帧数据收完,不再接受数据
USART2_RX_STA = 1; //置一帧数据接收完标志
// GPIOA->ODR |= GPIO_Pin_8;
// GPIO_SetBits(GPIOA,GPIO_Pin_11);
}
break;
}
case U_FSM_DATA16:
{
USART2_RX_BUF[RX2_cn++] = u8Temp;
if(RX2_no <= RX2_cn)//数据接收完毕
{
u8Uart2_FSM = U_FSM_ADR;
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //一帧数据收完,不再接受数据
USART2_RX_STA = 1; //置一帧数据接收完标志
}
break;
}
default:{u8Uart2_FSM = U_FSM_ADR; break; }
}
}
}



    推荐阅读