#define __IN_SERIAL_C__ #include "config.h"
#define BAUDX 8// Baud rate divisor. #define BAUD(A) ((F_CPU/BAUDX/(A))-1)
#define UART_SEND_BUF_SIZE 16 //串口发送缓冲队列大小 #define UART_RECEIVE_BUF_SIZE 16 //串口接收缓冲队列大小
static uint8 g_uart_send_buf[UART_SEND_BUF_SIZE]; static uint8 g_uart_receive_buf[UART_RECEIVE_BUF_SIZE];
volatile static uint8 g_uart_send_buf_first_index=UART_SEND_BUF_SIZE-1; //指向最先进入发送缓冲队列的数据(的前一位) volatile static uint8 g_uart_send_buf_last_index=UART_SEND_BUF_SIZE-1; //指向最后进入发送缓冲队列的数据(的前一位)
volatile static uint8 g_uart_receive_buf_first_index=UART_RECEIVE_BUF_SIZE-1; //指向最先进入接收缓冲队列的数据(的前一位) volatile static uint8 g_uart_receive_buf_last_index=UART_RECEIVE_BUF_SIZE-1; //指向最后进入接收缓冲队列的数据(的前一位)
void usart_baud_init(uint16 ubrr ) { UBRRH = (uint8_t)(ubrr>>8); UBRRL = ubrr; UCSRA = (BAUDX == 8)?(1<<U2X):0; UCSRB = ((1<<TXEN) | (1<<RXEN));//| (1<<RXCIE)); UCSRC = ((1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0))|_BV(UPM1);//8数据,1停止,偶校验 }
void usart_init(void) { usart_baud_init(BAUD(9600) ); }
//循环加一,缓冲队列下一个数据的序号 //return=(val+1)%buf_size uint8 inc_cycle(uint8 val,uint8 buf_size) { val++; while(val>=buf_size) { val=val-buf_size; } return val; }
//串口数据寄存器空中断 //如果串口发送队列有数据,发送数据 //如果没有,关闭发送中断 SIGNAL(SIG_UART_DATA) { UCSRB &= ~_BV(UDRIE); //关闭发送 if(g_uart_send_buf_first_index!=g_uart_send_buf_last_index) //如果发送队列有未发送的数据 { g_uart_send_buf_first_index=inc_cycle(g_uart_send_buf_first_index,UART_SEND_BUF_SIZE);//送队列FIRST_INDEX循环加一,指向队列下一个数据 UDR =g_uart_send_buf[g_uart_send_buf_first_index]; //读取发送队列数据 UCSRB |= _BV(UDRIE); //打开发送 } }
uint8 uart_send_buf_put(data) { uint8 temp,inc_cycle_index; temp=__save_interrupt();//进入临界段 cli(); inc_cycle_index=inc_cycle(g_uart_send_buf_last_index,UART_SEND_BUF_SIZE); if(g_uart_send_buf_first_index!=inc_cycle_index)//如果发送队列数据未满 { g_uart_send_buf_last_index=inc_cycle_index; //发送队列LAST_INDEX循环加一 g_uart_send_buf[g_uart_send_buf_last_index]=data;//数据写入发送队列 __restore_interrupt(temp); //退出临界段 return 1; //数据写入发送队列正确返回 } else{ __restore_interrupt(temp); //退出临界段 return 0; //数据写入发送队列错误返回 } }
//用户API //把数据放到串口发送队列 uint8 uart_put_char(uint8 data)
{ uint8 temp; temp=uart_send_buf_put(data); //数据写入发送队列 UCSRB |= _BV(UDRIE); //打开发送中断 return temp; //返回写入发送队列是否正确 }
//用户API,阻塞函数 //连续把ucSize放到串口发送队列 void uart_block_send_data(uint8 *pucBuffer,uint8 ucSize) { uint8 i;
for(i = 0; i < ucSize; i++) { while(!uart_put_char(pucBuffer)); //发送连续多发数据,直到全部都正确写入发送队列 } }
//串口接收中断 SIGNAL(SIG_USART_RECV) { uint8 data,inc_cycle_index; UCSRB &= ~(1<<RXCIE); //关闭串口接收 data=UDR; //读取串口数据寄存器数据 inc_cycle_index=inc_cycle(g_uart_receive_buf_last_index,UART_RECEIVE_BUF_SIZE); if(g_uart_receive_buf_first_index!=inc_cycle_index)//如果串口接收队列未满 { g_uart_receive_buf_last_index=inc_cycle_index; //接收队列LAST_INDEX循环加一
g_uart_receive_buf[g_uart_receive_buf_last_index]=data; //数据写入串口接收队列 } UCSRB |= (1<<RXCIE); }
//从串口接收队列取出一个数据到pdata[] uint8 uart_receive_buf_get(uint8 *pdata) { uint8 temp; temp=__save_interrupt();//进入临界段 cli(); if(g_uart_receive_buf_first_index!=g_uart_receive_buf_last_index)//如果串口接收队列里有数据 { g_uart_receive_buf_first_index=inc_cycle(g_uart_receive_buf_first_index,UART_RECEIVE_BUF_SIZE);//串口接收队列FIRST_INDEX循环加1 *pdata=g_uart_receive_buf[g_uart_receive_buf_first_index];//读取串口接收队列数据 __restore_interrupt(temp); //退出临界段 return 1; //正确取出串口接收数据换回 } else { __restore_interrupt(temp); //退出临界段 return 0; //串口接收队列无数据取出返回 } }
//用户API,从串口接收队列取出一个数据到pdata[] uint8 uart_get_char(uint8 *pdata)
{ return uart_receive_buf_get(pdata); }
//用户API,阻塞函数 //连续从串口接收队列取ucSize个数据到pucBuffer[] void uart_block_receive_data(uint8 *pucBuffer, uint8 ucSize) { uint8 i;
for(i = 0; i < ucSize; i++) { while(!uart_get_char(&pucBuffer)); //连续接收多个数据,直道全部从接收队列取出 } }
我的测试程序,每1/20秒执行一次,用串口调试助手,每秒自动发1个字符,下位机收到后再发给上位机。 收发一段时间后下位机没有任何返回了。
if(uart_get_char(&val1)) { uart_put_char(val1); }
|