/******************** (C) COPYRIGHT 2008 litt ********************
* File Name : usart.c
* Author : luo yi ming
* Version : V1.0.0
* Date : 2012年12月28日
* Description : This file provides a set of functions needed to manage the
* communication between usart peripheral and RS485/HW/PLC.
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "includes.h"
#include "usart.h"
/* Private typedef -----------------------------------------------------------*/
struct UartFifo{
//rx 12byte
u8* rxBuf; //4
vu16 rxSize; //2
vu16 rxPush; //2
vu16 rxPop; //2
u16 rxCnt; //2
//tx 12byte
u8* txBuf; //4
vu16 txSize; //2
vu16 txPush; //2
vu16 txPop; //2
u16 txCnt; //2
//Isr 4byte
void (*isr)(uint8_t,enum UartIsrMod);
};//28
struct UartCfg{
struct UartFifo fifo;
USART_TypeDef* uart;
DMA_Channel_TypeDef* rxdma;
DMA_Channel_TypeDef* txdma;
};
/*struct UartReg{
USART_TypeDef* uart;
DMA_Channel_TypeDef* rxdma;
DMA_Channel_TypeDef* txdma;
};*/
/* Private define ------------------------------------------------------------*/
#define UART1_DMA_RX DMA1_Channel5
#define UART1_DMA_TX DMA1_Channel4
#define UART2_DMA_RX DMA1_Channel6
#define UART2_DMA_TX DMA1_Channel7
#define UART3_DMA_RX DMA1_Channel3
#define UART3_DMA_TX DMA1_Channel2
#define UART_REG_1 {USART1,UART1_DMA_RX,UART1_DMA_TX}
#define UART_REG_2 {USART2,UART2_DMA_RX,UART2_DMA_TX}
#define UART_REG_3 {USART3,UART3_DMA_RX,UART3_DMA_TX}
#define UART_REG_4 {UART4,NULL,NULL}
#define UART_REG_5 {UART5,NULL,NULL}
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
struct UartCfg UartCfgTab[UART_PORT_MAX];
//const struct UartReg UartRegTab[UART_PORT_MAX] = {UART_REG_1,UART_REG_2,UART_REG_3,UART_REG_4,UART_REG_5};
/*
UART running by interrupt model
*/
/*************************************************************************************************
* Name : UartIntIsr
* Describe : 串口中断服务程序
* Input : pfifo,uart
* Output : 无
* Create by : 罗一鸣 2012-12-03
* Moid by :
*************************************************************************************************/
static __inline void UartIntIsr(uint8_t port,struct UartFifo *pfifo,USART_TypeDef *uart)
{
uint32_t ie;
uint8_t c;
ie = __get_PRIMASK();
__set_PRIMASK(1);
if((uart->CR1 & 0x0020) && (uart->SR & 0x0020))
{
c = uart->DR;
if(pfifo->rxCnt < pfifo->rxSize)
{
pfifo->rxBuf[pfifo->rxPush] = c;
pfifo->rxPush += 1;
pfifo->rxPush %= pfifo->rxSize;
pfifo->rxCnt += 1;
if(pfifo->rxCnt == (pfifo->rxSize - SERIAL_RXFULL_LINE))
{
if(NULL != pfifo->isr)
{
pfifo->isr(port,RxFull);
}
}
}
}
//IDLE IRQ
if((uart->CR1 & 0x0010)&&(uart->SR & 0x0010))
{
c = uart->DR;
if(pfifo->rxCnt < (pfifo->rxSize - SERIAL_RXFULL_LINE))
{
if(NULL != pfifo->isr)
{
pfifo->isr(port,RxTimeout);
}
}
}
//TXE IRQ
if((uart->SR & 0x0080) && (uart->CR1 & 0x0080))
{
uart->CR1 &= (uint16_t)~0x0080; //off TX
if(pfifo->txCnt)
{
c = pfifo->txBuf[pfifo->txPop];
uart->DR = c;
uart->CR1 |= (uint16_t)0x0080;
pfifo->txPop += 1;
pfifo->txPop %= pfifo->txSize;
pfifo->txCnt -= 1;
if(pfifo->txCnt == 0)
{
if(NULL != pfifo->isr)
{
pfifo->isr(port,TxEmpty);
}
}
}
}
__set_PRIMASK(ie);
}
/*************************************************************************************************
* Name : UartRead
* Describe : 串口读取函数
* Input :
* Output :
* Create by :
* Moid by :
*************************************************************************************************/
static uint16_t UartReadInt(struct UartFifo *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
{
uint16_t n;
if(len == 0)
{
return 0;
}
else if(len > pfifo->rxSize)
{
len = pfifo->rxSize;
}
for(n=0;n<len;n++)
{
USART_ITConfig(uart,USART_IT_RXNE ,DISABLE);
if(pfifo->rxCnt > 0)
{
*data++ = pfifo->rxBuf[pfifo->rxPop];
pfifo->rxPop += 1;
pfifo->rxPop %= pfifo->rxSize;
pfifo->rxCnt--;
USART_ITConfig(uart,USART_IT_RXNE ,ENABLE);
}
else
{
USART_ITConfig(uart,USART_IT_RXNE ,ENABLE);
break;
}
}
return n;
}
/*************************************************************************************************
* Name : UartWrite
* Describe : 串口发送函数
* Input :
* Output :
* Create by :
* Moid by :
*************************************************************************************************/
static uint16_t UartWriteInt(struct UartFifo *pfifo,USART_TypeDef *uart,uint8_t *data,uint16_t len)
{
uint16_t n;
if(len == 0)
{
return 0;
}
else if(len > pfifo->txSize)
{
len = pfifo->txSize;
}
USART_ITConfig(uart,USART_IT_TXE ,DISABLE);
for(n=0;n<len;n++)
{
if(pfifo->txCnt < pfifo->txSize)
{
pfifo->txBuf[pfifo->txPush] = *data++;
pfifo->txPush += 1;
pfifo->txPush %= pfifo->txSize;
pfifo->txCnt++;
}
else
{
break;
}
}
USART_ITConfig(uart,USART_IT_TXE ,ENABLE);
return n;
}
/*************************************************************************************************
* Name : USART_ISR
* Describe : 串口中断服务
* Input :
* Output :
* Create by :
* Moid by :
*************************************************************************************************/
void USART_ISR(uint8_t port)
{
UartIntIsr(port,&UartCfgTab[port].fifo,UartCfgTab[port].uart);
}
/*
*/
__inline void UartDmaIsr(uint8_t port,struct UartFifo *pfifo,USART_TypeDef *uart)
{
}
/*
UART API
*/
/*************************************************************************************************
* Name : SerialPortConfig
* Describe :
* Input :
* Output :
* Create by : 罗一鸣 Date: 2012-12-03
* Moid by :
*************************************************************************************************/
void UartNvicSet(uint8_t port,uint8_t preprio,uint8_t subprio)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
if(UART_PORT_1 == port)
{
// config USART1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// Configure USART1 Tx (PA.09) as alternate function push-pull
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);
// Configure USART1 Rx (PA.10) as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Set Interrupt Priority
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//CLI();
NVIC_Init(&NVIC_InitStructure);
//SEI();
}
else if(UART_PORT_2 == port)
{
// config USART2 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// Configure USART2 Tx (PA.02) as alternate function push-pull
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);
// Configure USART2 Rx (PA.03) as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Set Interrupt Priority
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//CLI();
NVIC_Init(&NVIC_InitStructure);
//SEI();
}
else if(UART_PORT_3 == port)
{
// config USART3 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// Configure USART2 Tx (PB.10) as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Configure USART2 Rx (PB.11) as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Set Interrupt Priority
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preprio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = subprio;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//CLI();
NVIC_Init(&NVIC_InitStructure);
//SEI();
}
}
/*************************************************************************************************
* Name : UartConfig
* Describe :
* Input :
* Output :
* Create by : 罗一鸣 Date: 2012-12-03
* Moid by :
*************************************************************************************************/
void UartConfig(uint8_t port,uint8_t *buf,uint16_t size,void (*isr)(uint8_t,enum UartIsrMod),FunctionalState dma)
{
switch(port)
{
case UART_PORT_1: UartCfgTab[port].uart = USART1;UartCfgTab[port].rxdma = UART1_DMA_RX;UartCfgTab[port].txdma = UART1_DMA_TX;break;
case UART_PORT_2: UartCfgTab[port].uart = USART2;UartCfgTab[port].rxdma = UART2_DMA_RX;UartCfgTab[port].txdma = UART2_DMA_TX;break;
case UART_PORT_3: UartCfgTab[port].uart = USART3;UartCfgTab[port].rxdma = UART3_DMA_RX;UartCfgTab[port].txdma = UART3_DMA_TX;break;
case UART_PORT_4: UartCfgTab[port].uart = UART4;break;
case UART_PORT_5: UartCfgTab[port].uart = UART5;break;
default : return;
}
UartCfgTab[port].fifo.rxBuf = buf;
UartCfgTab[port].fifo.txBuf = buf+size/2;
UartCfgTab[port].fifo.rxSize = UartCfgTab[port].fifo.txSize = size/2;
UartCfgTab[port].fifo.rxPush = UartCfgTab[port].fifo.rxPop = UartCfgTab[port].fifo.rxCnt = 0;
UartCfgTab[port].fifo.txPush = UartCfgTab[port].fifo.txPop = UartCfgTab[port].fifo.txCnt = 0;
UartCfgTab[port].fifo.isr = isr;
if(DISABLE == dma)
{
UartCfgTab[port].rxdma = NULL;
UartCfgTab[port].txdma = NULL;
USART_ITConfig(UartCfgTab[port].uart,USART_IT_TXE ,DISABLE);
USART_ITConfig(UartCfgTab[port].uart,USART_IT_RXNE,ENABLE);
USART_ITConfig(UartCfgTab[port].uart,USART_IT_IDLE,ENABLE);
USART_Cmd(UartCfgTab[port].uart, ENABLE);
}
else
{
USART_ITConfig(UartCfgTab[port].uart,USART_IT_IDLE,ENABLE);
USART_Cmd(UartCfgTab[port].uart, ENABLE);
}
}
/*************************************************************************************************
* Name : UartOpen
* Describe :
* Input :
* Output :
* Create by : 罗一鸣 Date: 2013-02-27
* Moid by :
*************************************************************************************************/
void UartOpen(uint8_t port,uint32_t baud,uint8_t mod)
{
USART_InitTypeDef init;
init.USART_BaudRate = baud;
init.USART_WordLength = USART_WordLength_8b;
init.USART_StopBits = USART_StopBits_1;
init.USART_Parity = USART_Parity_No ;
if(mod & UART_FLOW_EN)
{
init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
}
init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(UartCfgTab[port].uart, &init);
}
/*************************************************************************************************
* Name : UartRead
* Describe :
* Input :
* Output :
* Create by : 罗一鸣 Date: 2012-12-03
* Moid by :
*************************************************************************************************/
uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len)
{
if(UART_PORT_MAX <= port)
{
return 0;
}
if((NULL != UartCfgTab[port].rxdma))
{
return 0;
}
else
{
return UartReadInt(&UartCfgTab[port].fifo,UartCfgTab[port].uart,data,len);
}
}
/*************************************************************************************************
* Name : UartWrite
* Describe :
* Input :
* Output :
* Create by : 罗一鸣 Date: 2012-12-03
* Moid by :
*************************************************************************************************/
uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len)
{
if(UART_PORT_MAX <= port)
{
return 0;
}
if((NULL != UartCfgTab[port].txdma))
{
return 0;
}
else
{
return UartWriteInt(&UartCfgTab[port].fifo,UartCfgTab[port].uart,data,len);
}
}
/*************************************************************************************************
* Name : UartRxCnt
* Describe :
* Input :
* Output :
* Create by :
* Moid by :
*************************************************************************************************/
uint16_t UartRxCnt(uint8_t port)
{
return UartCfgTab[port].fifo.rxCnt;
}
/*************************************************************************************************
* Name : UartTxCnt
* Describe :
* Input :
* Output :
* Create by :
* Moid by :
*************************************************************************************************/
uint16_t UartTxCnt(uint8_t port)
{
return UartCfgTab[port].fifo.txCnt;
}
/****************************************************************************
*************************** End of File *************************************
****************************************************************************/