#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;
}
}
}
}