zoukankan      html  css  js  c++  java
  • 【转】Atmega32串口驱动(基于ucos)——循环缓冲区

    原文地址:http://bbs.ednchina.com/BLOG_ARTICLE_235210.HTM

    /* ******************************************************************
     * Filename: uart.c
     * Author: lstzixing
     * Mail: blievethink@gmail.com
     * Date: 2009-5-26
     * Description: 串口数据收发接口. For Atmega32
     * ****************************************************************** */

    #include "app.h"

    // 对发送缓冲,信号计数为空闲字符数

    // 对接收缓冲,计数为缓冲已有计数
    typedef struct  _FIFO

        INT8U * buf;                                // FIFO缓冲区
        INT8U * in, * out;                          // FIFO读写指针
        OS_EVENT * sem;                             // FIFO读写同步信号量
    }FIFO;

    static INT8U UartTxBuf[ UART_TX_LEN ];          // 发送缓冲

    static INT8U UartRxBuf[ UART_RX_LEN ];          // 接收缓冲
    static FIFO UartTxFifo, UartRxFifo;             // 收发缓冲控制FIFO结构

    OS_SEM_DATA SemData;

    static INT8U UartPutRxChar( INT8U c );

    static INT8U UartGetTxChar( INT8U * err );

    #define UartStartTx()   { UCSRB |=  1<<UDRIE; }

    #define UartStopTx()    { UCSRB &= ~(1<<UDRIE); } 
    #define UartStartRx()   { UCSRB |=  1<<RXCIE; }
    #define UartStopRx()    { UCSRB &= ~( 1<<RXCIE ); }
    /* ****************************************************************
     *              UartFlush()
     * 功能:缓冲清空
     * 参数: isTxBuf ------ 是否为发送缓冲
     * 返回值:None
     * 说明:清空收发缓冲
     * *************************************************************** */           
    void    UartFlush( INT8U isTxBuf )
    {
    #if OS_CRITICAL_METHOD == 3
        OS_CPU_SR   cpu_sr;
    #endif
        INT8U cnt;

        OS_ENTER_CRITICAL();

        if( isTxBuf )

        {
            UartTxFifo.buf = UartTxBuf;                             // 复位发送缓冲读写指针
            UartTxFifo.in = UartTxBuf;
            UartTxFifo.out = UartTxBuf;
            OSSemQuery( UartTxFifo.sem, &SemData );
            cnt = UART_TX_LEN - SemData.OSCnt;                      // 在其它地方必须保证SemData.OSCnt < UART_TX_LEN
            while( cnt-- )
                OSSemPost( UartTxFifo.sem );                        // 复位发送信号量值为UART_TX_LEN
        }

        else

        {
            UartRxFifo.buf = UartRxBuf;                             // 复位接收缓冲读写指针
            UartRxFifo.in = UartRxBuf;
            UartRxFifo.out = UartRxBuf;
            while( OSSemAccept( UartRxFifo.sem ) );                 // 复位接收信号量值为0

        }

        OS_EXIT_CRITICAL();
    }

    void    UartPutStr( char * str )
    {
        char    * ptr;

        ptr = (char *)str;

        while(*ptr != '')

            UartPutChar( *ptr++, 0 );
        
    }
    /* *****************************************************************
     *          UartPutChar()
     * 函数名:UartPutChar()
     * 功能: 发送一字节至串口缓冲区
     * 参数: c ----------- 要发送的字节
     *      to ---------- 指定的等待操作完成的超时时间
     * 返回值: OS_NO_ERR --- 操作成功
     *        OS_TIMEOUT --- 操作超时
     * 说明:
     * ***************************************************************** */
    INT8U UartPutChar( INT8U c, INT16U to )
    {
    #if OS_CRITICAL_METHOD == 3
        OS_CPU_SR   cpu_sr;
    #endif
        INT8U   err;

        OSSemPend( UartTxFifo.sem, to, &err );                  // 等待发送缓冲可用

        if( err == OS_NO_ERR )

        {
            OS_ENTER_CRITICAL();
            *(UartTxFifo.in)++ = c;         
            if( UartTxFifo.in >= UartTxBuf +  UART_TX_LEN)      // 调整指针
                UartTxFifo.in = UartTxBuf;

            OS_EXIT_CRITICAL();

            // 启动发送

            UartStartTx();
        }

        return  err;

    }

    /* ***************************************************************
     *          UartGetChar()
     * 函数名:UartGetChar()
     * 功能:从接收缓冲区中取一字节
     * 参数: to --- 指定的超时量
     *      err --- 指定存储错误变量
     *         OS_TIMEOUT / OS_NO_ERR
     * 返回值: 接收的字节
     * 说明:NO
     * *************************************************************** */
    INT8U   UartGetChar( INT16U to, INT8U * err  )
    {
    #if OS_CRITICAL_METHOD == 3
        OS_CPU_SR   cpu_sr;
    #endif
        INT8U   c;

        c = 0;

        OSSemPend( UartRxFifo.sem, to, err );

        if( *err != OS_TIMEOUT ) 

        {
            OS_ENTER_CRITICAL();
            c = *(UartRxFifo.out)++;                                // 写入字节
            if( UartRxFifo.out >= UartRxBuf + UART_RX_LEN )         // 调整指针
                UartRxFifo.out = UartRxBuf;
            OS_EXIT_CRITICAL();

            UartStartRx();                                          // 接收缓冲非满,使能接收

        }
      
        return  c;
    }


    /* ******************************************************************
     *          UartHdInit()
     * 函数名:UartInit()
     * 说明:
     * 参数:baudrate ----- 波特率
     *  partity ------ 奇偶校验方式
     *  stops   ------ 停止位数 
     *  len   -------- 数据帧长度
     * 说明:此函数必须最先被调用   
     * ****************************************************************** */    
    void    UartInit( void )
    {
    #if OS_CRITICAL_METHOD == 3
        OS_CPU_SR   cpu_sr;
    #endif
        UartTxFifo.sem =  OSSemCreate( UART_TX_LEN );               // 发送结构初始化
        UartTxFifo.buf = UartTxBuf;
        UartTxFifo.in = UartTxFifo.out = UartTxBuf;

        UartRxFifo.sem =  OSSemCreate( 0 );                         // 接收结构初始化
        UartRxFifo.buf = UartRxBuf;
        UartRxFifo.in = UartRxFifo.out = UartRxBuf;

        // 初始化串口,设置baudrate, len, parity, stops -- 

        OS_ENTER_CRITICAL();
    //  UCSRA = 0xff;                                           
        UCSRB = 1<<RXCIE | 1<<RXEN | 1<<TXEN;                               // 收发使能,接收中断
        UCSRC =  1<<URSEL| 1<<UPM1| 1<<UPM0| 1<<UCSZ1| 1<<UCSZ0;            // 异步,8位字节,奇校验
        UBRRL = ((INT32U)F_OSC / (16*(INT32U)UART_BAUD ) - 1 ) & 0xff;      // 设置波特率
        UBRRH = ((INT32U)F_OSC / (16*(INT32U)UART_BAUD ) - 1 ) >> 8;
        OS_EXIT_CRITICAL();
    }

    void  UartTxIsr( void )                                                 // 发送寄存器空中断
    {   
        INT8U   err, c;

        c = UartGetTxChar( &err );

        if( err == UART_OK )
            UDR = c;                                                        // 发送数据
    }

    void  UartRxIsr( void )                                                 // 发送寄存器空中断
    {
        INT8U   err, c;

        err = UCSRA;

        c = UDR;
        if( !(err & ( DOR|PE|FE )) )
            UartPutRxChar( c );
    }
    /* *****************************************************************
     *                      UartPutRxChar()
     * 函数名: UartPutRxChar()
     * 参数:c ----- 要写入的字符
     * 返回值:UART_OK --- 操作成功
     *          UART_BUF_FULL -- 失败,缓冲满
     * 说明:此函数仅供中断系统调用
     * ***************************************************************** */
    static INT8U UartPutRxChar( INT8U c )
    {
        OSSemQuery( UartRxFifo.sem, &SemData );
        if( SemData.OSCnt < UART_RX_LEN )                                   // 缓冲不满
        {
            *(UartRxFifo.in)++ = c;
            if( UartRxFifo.in >= UartRxBuf + UART_RX_LEN )
                UartRxFifo.in = UartRxBuf;
            OSSemPost( UartRxFifo.sem );                                    // 向任务发送信号量

            return  UART_OK;

        }       
        else
        {
            UartStopRx();                                                   // 缓冲满,不再接收数据
            return  UART_BUF_FULL;
        }
    }

    /* *****************************************************************
     *                      UartGetTxChar()
     * 函数名: UartGetTxChar()
     * 参数:err ---- 错误参量
     * 返回值:UART_OK
     *          UART_BUF_EMPTY --- 失败,缓冲空
     * 说明:
     * ***************************************************************** */
    static INT8U    UartGetTxChar( INT8U * err )
    {
        INT8U c;

        c = 0;

        OSSemQuery( UartTxFifo.sem, &SemData );
        if( SemData.OSCnt < UART_TX_LEN )                                   // <TX_LEN, 缓冲有数据可发送
        {
            c = *(UartTxFifo.out)++;
            if( UartTxFifo.out >= UartTxBuf + UART_TX_LEN )
                    UartTxFifo.out = UartTxBuf;
            OSSemPost( UartTxFifo.sem );                                    // 向任务发送信号量
            *err = UART_OK;
        }       
        else
        {
            UartStopTx();                                                   // 缓冲空,不再使能发送中断
            *err = UART_BUF_EMPTY;
        }

        return  c;

    }

  • 相关阅读:
    C# 图片与Base64的相互转化
    LeetCode 303. Range Sum Query – Immutable
    LeetCode 300. Longest Increasing Subsequence
    LeetCode 292. Nim Game
    LeetCode 283. Move Zeroes
    LeetCode 279. Perfect Squares
    LeetCode 268. Missing Number
    LeetCode 264. Ugly Number II
    LeetCode 258. Add Digits
    LeetCode 257. Binary Tree Paths
  • 原文地址:https://www.cnblogs.com/codecamel/p/4688416.html
Copyright © 2011-2022 走看看