CS代写 SYSCLK 16000000L

* FILE: serialio.c
* Written by .
* Module to allow standard input/output routines to be used via
* serial port 0. The init_serial_stdio() method must be called before

Copyright By PowCoder代写 加微信 powcoder

* any standard IO methods (e.g. printf). We use interrupt-based output
* and a circular buffer to store output messages. (This allows us
* to print many characters at once to the buffer and have them
* output by the UART as speed permits.) If the buffer fills up, the
* put method will either
* (1) if interrupts are enabled, block until there is room in it, or
* (2) if interrupts are disabled, will discard the character.
* Input is blocking – requesting input from stdin will block
* until a character is available. If interrupts are disabled when
* input is sought, then this will block forever.
* The function input_available() can be used to test whether there is
* input available to read from stdin.

#include
#include

#include
#include

/* System clock rate in Hz. (L at the end indicates this is a long constant) */
#define SYSCLK 16000000L

/* Global variables */
/* Circular buffer to hold outgoing characters. The insert_pos variable
* keeps track of the position (0 to OUTPUT_BUFFER_SIZE-1) that the next
* outgoing character should be written to. bytes_in_buffer keeps
* count of the number of characters currently stored in the buffer
* (ranging from 0 to OUTPUT_BUFFER_SIZE). This number of bytes immediately
* prior to the current insert_pos are the bytes waiting to be output.
* If the insert_pos reaches the end of the buffer it will wrap around
* to the beginning (assuming those bytes have been output).
* NOTE – OUTPUT_BUFFER_SIZE can not be larger than 255 without changing
* the type of the variables below (currently defined as 8 bit unsigned ints).
#define OUTPUT_BUFFER_SIZE 255
volatile char out_buffer[OUTPUT_BUFFER_SIZE];
volatile uint8_t out_insert_pos;
volatile uint8_t bytes_in_out_buffer;

/* Circular buffer to hold incoming characters. Works on same principle
* as output buffer
#define INPUT_BUFFER_SIZE 16
volatile char input_buffer[INPUT_BUFFER_SIZE];
volatile uint8_t input_insert_pos;
volatile uint8_t bytes_in_input_buffer;
volatile uint8_t input_overrun;

/* Variable to keep track of whether incoming characters are to be echoed
* back or not.
static int8_t do_echo;

/* Function prototypes
void init_serial_stdio(long baudrate, int8_t echo);
static int uart_put_char(char, FILE*);
static int uart_get_char(FILE*);

/* Setup a stream that uses the uart get and put functions. We will
* make standard input and output use this stream below.
static FILE myStream = FDEV_SETUP_STREAM(uart_put_char, uart_get_char,
_FDEV_SETUP_RW);

void init_serial_stdio(long baudrate, int8_t echo) {
uint16_t ubrr;
* Initialise our buffers
out_insert_pos = 0;
bytes_in_out_buffer = 0;
input_insert_pos = 0;
bytes_in_input_buffer = 0;
input_overrun = 0;

* Record whether we’re going to echo characters or not
do_echo = echo;

/* Configure the serial port baud rate */
/* (This differs from the datasheet formula so that we get
* rounding to the nearest integer while using integer division
* (which truncates)).
ubrr = ((SYSCLK / (8 * baudrate)) + 1)/2 – 1;
UBRR0 = ubrr;

* Enable transmission and receiving via UART. We don’t enable
* the UDR empty interrupt here (we wait until we’ve got a
* character to transmit).
* NOTE: Interrupts must be enabled globally for this
* library to work, but we do not do this here.
UCSR0B = (1<= OUTPUT_BUFFER_SIZE) {
if(!interrupts_enabled) {
/* else do nothing */

/* Add the character to the buffer for transmission if there
* is space to do so. We advance the insert_pos to the next
* character position. If this is beyond the end of the buffer
* we wrap around back to the beginning of the buffer
* NOTE: we disable interrupts before modifying the buffer. This
* prevents the ISR from modifying the buffer at the same time.
* We reenable them if they were enabled when we entered the
* function.
out_buffer[out_insert_pos++] = c;
bytes_in_out_buffer++;
if(out_insert_pos == OUTPUT_BUFFER_SIZE) {
/* Wrap around buffer pointer if necessary */
out_insert_pos = 0;
/* Reenable interrupts (UDR Empty interrupt may have been
* disabled) – we ensure it is now enabled so that it will
* fire and deal with the next character in the buffer. */
UCSR0B |= (1 << UDRIE0); if(interrupts_enabled) { int uart_get_char(FILE* stream) { /* Wait until we've received a character */ while(bytes_in_input_buffer == 0) { /* do nothing */ * Turn interrupts off and remove a character from the input * buffer. We reenable interrupts if they were on. * The pending character is the one which is byte_in_input_buffer * characters before the insert position (taking into account * that we may need to wrap around). uint8_t interrupts_enabled = bit_is_set(SREG, SREG_I); if(input_insert_pos - bytes_in_input_buffer < 0) { /* Need to wrap around */ c = input_buffer[input_insert_pos - bytes_in_input_buffer + INPUT_BUFFER_SIZE]; c = input_buffer[input_insert_pos - bytes_in_input_buffer]; /* Decrement our count of bytes in the input buffer */ bytes_in_input_buffer--; if(interrupts_enabled) { * Define the interrupt handler for UART Data Register Empty (i.e. * another character can be taken from our buffer and written out) ISR(USART_UDRE_vect) /* Check if we have data in our buffer */ if(bytes_in_out_buffer > 0) {
/* Yes we do – remove the pending byte and output it
* via the UART. The pending byte (character) is the
* one which is “bytes_in_buffer” characters before the
* insert_pos (taking into account that we may
* need to wrap around to the end of the buffer).
if(out_insert_pos – bytes_in_out_buffer < 0) { /* Need to wrap around */ c = out_buffer[out_insert_pos - bytes_in_out_buffer + OUTPUT_BUFFER_SIZE]; c = out_buffer[out_insert_pos - bytes_in_out_buffer]; /* Decrement our count of the number of bytes in the bytes_in_out_buffer--; /* Output the character via the UART */ /* No data in the buffer. We disable the UART Data * Register Empty interrupt because otherwise it * will trigger again immediately this ISR exits. * The interrupt is reenabled when a character is * placed in the buffer. UCSR0B &= ~(1<= INPUT_BUFFER_SIZE) {
input_overrun = 1;
/* If the character is a carriage return, turn it into a
* linefeed
if (c == ‘\r’) {

* There is room in the input buffer
input_buffer[input_insert_pos++] = c;
bytes_in_input_buffer++;
if(input_insert_pos == INPUT_BUFFER_SIZE) {
/* Wrap around buffer pointer if necessary */
input_insert_pos = 0;

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com