打印

今天听到一个关于中断的说,“实时和异步”,然后改进了UART的驱动

[复制链接]
2878|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
罗菜鸟|  楼主 | 2013-3-18 21:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
所谓实时,就是在中断里面及时处理
所谓异步,就是中断触发信号量,消息这些,在任务里面处理。
然后我改进了我的代码
/******************** (C) COPYRIGHT 2008 boost ********************
* File Name          : usart.h
* Author             : sms
* Version            : V1.0.0
* Date               : 2010年1月21日
* Description        : Header for usart.c module
********************************************************************************/

/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __USART_H
#define __USART_H

#define  SERIAL_RXFULL_LINE  16
#define  SERIAL_MIN_FIFO     32
#define  SERIAL_MAX_FIFO     1024

#define UART_RX_IDLE  0x01           // Uart Rx Idle Byte
#define UART_RX_FULL  0x02           // Uart Rx Buffer is 16 byte than full
#define UART_TX_DONE  0x04           // Uart Tx Buffer is empty

#define  UART_PORT_MAX            5

#define  UART_PORT_1              0
#define  UART_PORT_2              1
#define  UART_PORT_3              2
#define  UART_PORT_4              3
#define  UART_PORT_5              4

#define  UART_FLOW_EN             0x80
#define  UART_2STOP_EN            0x40
#define  UART_EVEN_EN             0x20
#define  UART_ODD_EN              0x10


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"


//typedef uint8_t UartBuf_t[28];




extern void UartNvicSet(uint8_t port,uint8_t preprio,uint8_t subprio);
extern void USART_ISR(uint8_t port);
extern void UartConfig(uint8_t port,uint8_t *buf,uint16_t size,void (*isr)(uint8_t,uint8_t),FunctionalState dma);
extern void UartOpen(uint8_t port,uint32_t baud,uint8_t mod);
extern uint16_t UartRead(uint8_t port,uint8_t *data,uint16_t len);
extern uint16_t UartWrite(uint8_t port,uint8_t *data,uint16_t len);
/*
extern void UartIsr(struct UartPort port);
extern uint16_t UartRead(struct UartPort port,uint8_t *data,uint16_t len);
extern uint16_t UartWrite(struct UartPort port,uint8_t *data,uint16_t len);
extern uint16_t UartRxCnt(struct UartPort port);
extern uint16_t UartTxCnt(struct UartPort port);
extern void UartInit(struct UartPort port,uint16_t size,uint8_t *buf,void(*isr)(enum UartIsrMod));
extern void UartPortConfig(struct UartPort port,uint8_t preprio,uint8_t subprio);
*/

#endif /* __USART_H */

/******************* (C) COPYRIGHT 2008 boost *****END OF FILE****/
/******************** (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 port,uint8_t isrType);
};//28


struct UartCfg{
        struct UartFifo  fifo;
  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,isr_type = 0;
        ie = __get_PRIMASK();
        __set_PRIMASK(1);
        //RX IRQ
        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 - 16))
                        {
                                isr_type |=  UART_RX_FULL;
                        }
                }
        }
        //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)
                        {
                                isr_type |=  UART_TX_DONE;
                        }
                }
        }
        //IDLE IRQ
        if((uart->CR1 & 0x0010)&&(uart->SR & 0x0010))
        {
                c = uart->DR;
                if(pfifo->rxCnt <= (pfifo->rxSize - 16))
                {
                        isr_type |=  UART_RX_IDLE;
                }
        }
        __set_PRIMASK(ie);
        if((NULL != pfifo->isr) && (0 != isr_type))
        {
                pfifo->isr(port,isr_type);
        }
}


/*************************************************************************************************
* 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,uint8_t),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 *************************************
****************************************************************************/
沙发
罗菜鸟|  楼主 | 2013-3-18 21:22 | 只看该作者
二楼公布两点。
我的方法是在传统的queue的串口收发,但是增加了一个供OS使用的回调函数,回调函数有三种情况:接收queue收满(实际还差16个字节满),接收queue没有满但是传输方断流,形成了“空泡”(STM32的UART在接收数据流时产生1BYTE的“空泡”会有一个IDLE中断),发送queue发送空了。

回调函数在中断服务程序的最后阶段执行,通过先前的标志位来判断有哪些中断事件发生,如果仅仅是接收1个字节或者发送1个字节,是不会产生中断回调函数的,这就是一种实时。这样在OS调用回调函数时,可以通过标志位,来判断发生的中断类型,去触发对应的消息。另外中断在进行queue和标志位相关处理时,屏蔽了全局中断,这时候是不允许中断嵌套的。而到了回调函数的时候,全局中断开了,允许中断嵌套。



进一步计划,我打算在UCOS里,优先级最高的任务,去接收回调函数发来的信息。发送的信息采用消息队列,消息队列里面装的是函数指针,这样,我可以自定义不同的UART口在收到数据流,或者发完数据流后的不同处理函数,而且我可以在一个任务里面完成多个UART的处理,大大节约RAM

使用特权

评论回复
板凳
aihe| | 2013-3-18 21:51 | 只看该作者
顶一把

使用特权

评论回复
地板
zqh1630| | 2013-3-19 10:26 | 只看该作者
顶个!!!

使用特权

评论回复
5
罗菜鸟|  楼主 | 2013-3-19 10:42 | 只看该作者
你们给点意见嘛,不要顶,我是来求鄙视的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

132

主题

522

帖子

8

粉丝