/*************************************************** **文件名 :usart.c **功能 :usart标准有关的函数实现 **建立日期:07/11/14 **版本 :Ver1.0 **说明 : **修改记录: *****************************************************/ #include "config.h" #include "Port.h" #include "usart.h" #include /****一般情况下,与PC通信,接收缓冲区应适当的比发送缓冲区大*****/ #define XBUFLEN 4 //发送缓冲区的长度 #define RBUFLEN 8 //接收缓冲区的长度 /* 可以根据实际情况把缓冲区定义在idata,pdata,xdata*/ static uint8 rbuf[RBUFLEN], xbuf[XBUFLEN];/*这两个缓冲区遵循队列的先进先出原则*/ static volatile uint8 rcnt, xcnt, rpos, xpos;/*分别用来指示缓冲区的长度和将要出队的数据位置*/ static volatile uint8 busy;/*指示发送是否忙*/ /************************************************************ *名称:ser_init *功能:串口初始化子程序 *参数:需要设定的波特率 *返回:无 *说明: *************************************************************/ void ser_init (uint16 baud) { uint16 reg; rcnt = xcnt = rpos = xpos = 0; /* 初始化buffer */ busy = 0; UCSRB = _BV(RXCIE)|_BV(TXCIE)|_BV(RXEN)|_BV(TXEN); //rx,tx enable and interrupt enable UCSRC = _BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0); //8bit, not paitry,one stop bit reg = Fosc/(baud*16)-1; UBRRH=(uint8)reg>>8; UBRRL=(uint8)reg; sei(); //enable global interrupt flag } SIGNAL(SIG_UART_RECV) { if (rcnt < RBUFLEN) /* 判断是否还有缓冲区空间可以存放,防止覆盖缓冲区已经存在的数据 */ rbuf [(uint8)(rpos+rcnt++) % RBUFLEN] = UDR; } SIGNAL(SIG_UART_TRANS) { if (busy = xcnt) /*注意:这里并不是比较,而是赋值运算,用来判断是否有数据需要发送*/ { xcnt--; /*有数据需要发送*/ UDR = xbuf [xpos++]; if (xpos >= XBUFLEN) xpos = 0; } } /************************************************************ *名称:usart_putchar *功能:串口发送数据函数 *参数:c--要发送的数据 *返回:无 *说明:根据发送是否忙,将进行相应的处理 *************************************************************/ void usart_putchar (uint8 c) { while (xcnt >= XBUFLEN) /* 等待发送缓冲区有空间可以使用 */ ; cli(); //关中断 if (busy) { //如果发送正忙 xbuf[(uint8)(xpos+xcnt++) % XBUFLEN] = c; //送入发送缓冲区 } else { UDR = c; //直接发送 busy = 1; } sei(); //开中断 } /************************************************************ *名称:usart_getchar *功能:串口接收数据函数 *参数:无 *返回:接收的数据 *说明:直接从接收缓冲区取数据 *************************************************************/ uint8 usart_getchar (void) { uint8 c; while (!rcnt) /* 等待接收缓冲取有数据可读 */ ; cli(); rcnt--; c = rbuf [rpos++]; if (rpos >= RBUFLEN) rpos = 0; sei(); return (c); } /************************************************************ *名称:usart_puts *功能:串口发送字符串函数 *参数:s--发送的字符串地址 *返回:无 *说明:直接调用usart_putchar发送 *************************************************************/ void usart_puts (uint8 *s) { uint8 c; while (c=*s++) { if (c == '\n') usart_putchar ('\r'); usart_putchar (c); } } /************************************************************ *名称:usart_gets *功能:串口接收送字符函数 *参数:s--接收字符串地址 len--要接收的长度 *返回:无 *说明:直接调用usart_getchar接收 *************************************************************/ void usart_gets (uint8 *s, uint8 len) { uint8 pos, c; pos = 0; while (pos <= len) { c = usart_getchar (); if (c == '\r') continue; /* 丢弃 CR */ s[pos++] = c; if (c == '\n') break; /* 接收到一行 */ } s[pos] = '\0'; } /************************************************************ *名称:Ser_Can_Xmt *功能:发送缓冲区还可以接收数据的长度 *参数: *返回:返回可放到发送缓冲区的数据长度 *说明: *************************************************************/ uint8 ser_can_xmt (void) { return XBUFLEN - xcnt; } /************************************************************ *名称:Ser_Can_Rcv *功能:接收缓冲区已经有的数据长度 *参数:无 *返回:可读取数据的长度 *说明: *************************************************************/ uint8 ser_can_rcv (void) { return rcnt; }