Atmega32串口驱动(基于ucos)——循环缓冲区

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

/* ******************************************************************
 * Filename: uart.c
 * Author: lstzixing
 * Mail: [email protected]
 * 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 != ‘\0‘)

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;

}

时间: 2024-10-28 15:47:18

Atmega32串口驱动(基于ucos)——循环缓冲区的相关文章

[stm32][ucos] 1、基于ucos操作系统的LED闪烁、串口通信简单例程

* 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了5个任务            任务名                                             优先级            APP_TASK_START_PRIO                               2            主任务                          Task_Com1_PRIO                                

Smart210学习记录------linux串口驱动

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27025492&id=327609 一.核心数据结构 串口驱动有3个核心数据结构,它们都定义在<#include linux/serial_core.h> 1.uart_driver uart_driver包含了串口设备名.串口驱动名.主次设备号.串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver). struct

linux串口驱动分析

linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作.UART 使用系统时钟能够支持最高 115.2Kbps 的波特率.每一个 UART 通道对于接收器和发送器包含了 2 个 64 位的 FIFO. 寄存器 名称 地址 在linux中的描写叙述 (2410 和 2440 处理器对内存地址映射关系同样) UART 线性控制寄存器(ULCONn) ULC

高效的两段式循环缓冲区──BipBuffer

Simon Cooke,美国 (原作者) 北京理工大学 20981 陈罡(翻译) 写在前面的话: 循环缓冲区是一个非常常用的数据存储结构,已经被广泛地用于连续.流数据的存储和通信应用中.对于循环缓冲区,传统的操作方法是开辟一块连续的存储区,不 断地写入数据,当写入到存储区的末尾的时候,再从存储区的首部再开始写入数据,由此不断地重复下去构成了循环缓冲区.偶曾经写过很多循环缓冲区,也看过很 多人编写的循环缓冲区,但是拜读Simon Cooke先生的文章────“两段式”循环缓冲区(原文名称是:The

tiny4412 串口驱动分析 --- u-boot中的串口驱动

作者:彭东林 邮箱:[email protected] 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 u-boot:U-Boot 2010.12 Linux内核版本:linux-3.0.31 Android版本:android-4.1.2 我们以tiny4412为例分析串口驱动,下面我们从u-boot开始分析,然后再分析到Linux. 串口初始化 关于这部分代码流程参考件:tiny4412 u-boot 启动

12.2440串口驱动程序设计

12.2440串口驱动程序设计 串口的功能就是接受数据跟发送数据的,在上一节已经了解串口的引脚信号.但是数据的收发需要一定的条件,也就是串口的初始化.所以所以今天的内容就会被划分为三个部分: 1.串口的初始化: 创建一个uart.c来对串口进行处理,然后把它加入到Makefile工程文件里: 接着就是串口处理程序的实现了. 程序的刚开始是对串口进行初始化,初始化的步骤: 配置引脚功能 设置数据模式 设置工作模式 设置波特率. 1)配置引脚功能: 在2440里的串口底板原理图: 上面的11 TXD

tiny4412 串口驱动分析七 --- log打印的几个阶段之内核启动阶段(earlyprintk)

作者:彭东林 邮箱:[email protected] 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 u-boot:U-Boot 2010.12 Linux内核版本:linux-3.0.31 Android版本:android-4.1.2 下面要分析的是内核Log打印的几个阶段 自解压阶段 内核启动阶段 内核启动完全以后 shell终端下 在这个阶段内核log打印可以调用printk和printascii,同

BM77SPPS3蓝牙模块串口驱动研究(笔记本通过串口软件调试蓝牙模块)

最近接收一个项目,需要使用microchip公司出品的蓝牙模块,该模块自带陶瓷天线,蓝牙通信有效距离达到20米,支持串口.I2C驱动.本人主要是研究串口驱动,因为是第一次接触蓝牙,那么首先需要对一些概念进行熟悉. 该蓝牙模块的技术资料可以从网址下载:http://download.csdn.net/detail/camelbrand/8957967,首选需要了解该模块的硬件连接图,根据前面下载的资料手册<BM77_Data_Sheet_v2.0r>该模块的封装图如下图所示 本人只使用蓝牙模块的

伽利略板子串口驱动安装问题

上电一会就发烫 把usb连接电脑 ,提示安装驱动,自动安装不成功,然后我在网上找一帖看他们流程进行安装,提示串口安装成功,但是arduino软件中不显示刚在装的串口. 解决方法:   安装驱动和其它软件 Windows: (1) 如果没有完成,连接5V电源到Galileo开发板.(备注: 在连接USB前,始终连接5V电源.) (2) 连接USB数据线到板子USB client 端口(靠近以太网端)并且连接到PC USB段,等待windows驱动安装流程,几分钟后将提示安装驱动失败. (3) 点击