📄 uart.c
字号:
/* Name: uart.c * Project: AVR USB driver for CDC interface on Low-Speed USB * Author: Osamu Tamura * Creation Date: 2006-06-18 * Tabsize: 4 * Copyright: (c) 2006 by Recursion Co., Ltd. * License: Proprietary, free under certain conditions. See Documentation. *//*General Description: This module implements the UART rx/tx system of the USB-CDC driver.Note: This module violates the rule that interrupts must not be disabled forlonger than a couple of instructions (see usbdrv.h). Running UART interrupthandlers with sei as the first instruction is not possible because it wouldrecurse immediately (the cause of the interrupt has not been removed). Ifwe collect the data and then call sei(), we win little. We therefore decideto violate the rule. The effect on USB operation is, that packages may belost. This is equivalent to a package being dropped due to a CRC error. Thehost will therefore retry the transfer after a timeout. It is therefore verylikely that no effect is seen at the application layer.*/#include <avr/io.h>#include <avr/interrupt.h>#include <avr/pgmspace.h> /* needed by usbdrv.h */#include "oddebug.h"#include "uart.h"#include "usbdrv.h" /* only for usbWord_t */#if UART_CFG_HAVE_USART/* UART buffer */uchar urptr, uwptr, irptr, iwptr;uchar rx_buf[RX_SIZE], tx_buf[TX_SIZE];#ifndef URSEL# define URSEL_MASK 0#else# define URSEL_MASK (1 << URSEL)#endifvoid uartInit(int baudrate, uchar parity, uchar stopbits, uchar databits){usbWord_t br; br.word = F_CPU/(16L * baudrate) - 1;#if DEBUG_LEVEL < 1 /* USART configuration */ UCSR0B = 0; UCSR0C = URSEL_MASK | ((parity==1? 3:parity)<<UPM00) | ((stopbits>>1)<<USBS0) | ((databits-5)<<UCSZ00); UBRR0L = br.bytes[0]; UBRR0H = br.bytes[1];#else DBG1(0xf0, br.bytes, 2);#endif /* DEBUG_LEVEL */ UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);}void uartPoll(void){ /* nothing to do: all handled in interrupts */}void uartStartTransmission(void){ cli(); UCSR0B |= 1<<UDRIE0; sei();}uchar uartRxIsBusy(void){ return UCSR0A & (1<<RXC0);}#ifndef SIG_USART_RECV /* ATMega8 compatibility */# define SIG_USART_RECV SIG_UART_RECV# define SIG_USART_DATA SIG_UART_DATA#endifSIGNAL(SIG_USART_RECV) /* runs with global interrupts enabled */{uchar status, data; status = UCSR0A; data = UDR0; status &= (1<<FE0) | (1<<DOR0) | (1<<UPE0); if(status == 0){ /* no receiver error occurred */ uchar nextIwptr = (iwptr + 1) & RX_MASK; if(urptr != nextIwptr){ /* there is room in the buffer */ rx_buf[iwptr] = data; iwptr = nextIwptr; } }/* In principle, we could stay in the interrupt handler and read data as long * as UCSR0A & (1<<RXC0) is nonzero. However, since we don't enable interrupts * during the entire interrupt handler, we want to return as fast as possible. */}SIGNAL(SIG_USART_DATA) /* runs with global interrupts enabled */{ UDR0 = tx_buf[irptr]; irptr = (irptr + 1) & TX_MASK; if(uwptr == irptr){ /* no more data to transmit */ UCSR0B &= ~(1<<UDRIE0); /* prevent further interrupts */ }}#endif /* UART_CFG_HAVE_USART */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -