• 【转】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;

    }

  • 相关阅读:
    css边框以及其他常用样式
    jemeter学习-badboy录制与代理服务器录制
    linux基础命令学习
    cookie与session
    网址保存
    安全性测试要点转摘
    Charles弱网测试转载
    java 中文乱码以及转码
    spring学习总结——高级装配学习四(运行时:值注入、spring表达式)
    spring学习总结——高级装配学习三(Bean的作用域)
  • 原文地址:https://www.cnblogs.com/codecamel/p/4688416.html
Copyright © 2020-2023  润新知