⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rp6uart.c

📁 RP6机器人范例程序。包括移动
💻 C
字号:
/* ****************************************************************************
 *                           _______________________
 *                           \| RP6  ROBOT SYSTEM |/
 *                            \_-_-_-_-_-_-_-_-_-_/         		 >>> COMMON
 * ----------------------------------------------------------------------------
 * ------------------- [c]2006 / 2007 - AREXX ENGINEERING ---------------------
 * -------------------------- http://www.arexx.com/ ---------------------------
 * ****************************************************************************
 * File: RP6uart.c
 * Version: 1.1
 * Target: RP6 Base & Processor Expansion - ATMEGA32
 * Author(s): Dominik S. Herwald
 * ****************************************************************************
 * Description:
 *
 * The RP6 UART Library. (UART = "Universal Aynchronous Receiver Transceiver")
 *
 * It contains data transfer functions for the UART. 
 * In this new version, the reception functions have been completely rewritten
 * and are now Interrupt based with a circular buffer.
 *
 * --------
 *
 * Hint: You should better leave all this as it is if you just started with
 * C programming, but it is a good idea to read the comments and review the
 * code, it will help you to understand C programming for AVR better.
 *
 * Of course you are free to add new functions and improvements to this
 * library and make them available to the public on the Internet.
 * Please use the changelog at the end of this file to document your
 * changes. And add your name (or nickname) to any new function or 
 * modification you added! E.g. a "modified by <nickname> at <date>" is 
 * always a good idea to show other users where and what you changed the 
 * source code!
 *
 * ****************************************************************************
 * CHANGELOG AND LICENSING INFORMATION CAN BE FOUND AT THE END OF THIS FILE!
 * ****************************************************************************
 */
 
/*****************************************************************************/
// Includes:

#include "RP6uart.h"

/*****************************************************************************/
// UART transmit functions:

/**
 * Write a single character to the UART.
 *
 * Example:
 *
 *			writeChar('R');
 *			writeChar('P');
 *			writeChar('6');
 *			writeChar('\n');
 *			// '\n' is a special code for the "new line" character!
 *			writeChar('0');
 *			writeChar(48); // 48 is ASCII code for '0'
 *			writeChar(49); // 1
 *			writeChar(50); // 2
 *			writeChar(51); // 3
 *			//...
 *
 *			would output:
 *			RP6
 *			00123
 *
 */
void writeChar(char ch)
{
    while (!(UCSRA & (1<<UDRE)));
    UDR = (uint8_t)ch;
}

/**
 * Writes a null terminated string or buffer from SRAM to UART.
 * Make sure that it really IS null terminated!
 * ("null terminated" means that the string has a null (=0) at the end.
 * this is automatically added to it by the compiler when you put the
 * string in double quotes like this: writeString("test");  )
 *
 * ATTENTION: This fills up SRAM Memory with the
 * strings, even if they are constant and never changed.
 * If you want to write constant text strings to the UART, better use
 * writeNStringP(const uint8_t *pstring) (s. below), which reads the
 * text from flash program memory and does not fill up the SRAM with
 * the string data!
 *
 * Example:
 *
 *			writeString("RP6 Robot System\n");
 *
 */
void writeString(char *string)
{
	while(*string)
		writeChar(*string++);
}
		
/**
 * Writes a null terminated string from flash program memory to UART.
 * You can use the macro writeString_P(STRING); , this macro
 * ensures that the String is stored in program memory only!
 * Otherwise you need to use PSTR("your string") from AVRLibC for this. 
 *
 * Example:
 *
 *			writeNStringP(PSTR("RP6 Robot System\n"));
 *
 *			// There is also a Macro that makes life easier and
 *			// you can simply write:
 *			writeString_P("RP6 Robot System\n");
 *
 */
void writeNStringP(const char *pstring)
{
    uint8_t c;
    for (;(c = pgm_read_byte_near(pstring++));writeChar(c));
}


/**
 * Writes a string with specified length and offset from SRAM to UART.
 * If it is a null terminated string, output will be stopped at the
 * end! It does not need to be null terminated, but it is recommended
 * to use only null terminated strings/buffers, otherwise the function could
 * output any SRAM memory data stored after the string until it reaches a 0
 * or the specified length.
 *
 * Example:
 *
 *			writeStringLength("RP6 Robot Sytem\n",16,0);
 *			// would output: "RP6 Robot Sytem\n"
 *			writeStringLength("RP6 Robot Sytem\n",11,4);
 *			// would output: "Robot System"
 * 			writeStringLength("RP6 Robot Sytem\n",40,4);
 *			// would output: "Robot System\n"
 *			// No matter if the specified length is 40 characters!
 *
 */
void writeStringLength(char *string, uint8_t length, uint8_t offset)
{
	for(string = &string[offset]; *string && length; length--)
		writeChar(*string++);
}

/**
 * Write a number (with specified base) to the UART.
 *
 * Example:
 *
 *			// Write a hexadecimal number to the UART:
 *			writeInteger(0xAACC,16);
 *			// Instead of 16 you can also write "HEX" as this is defined in the
 *			// RP6RobotBaseLib.h :
 *			writeInteger(0xAACC, HEX);
 *			// Other Formats:
 *			writeInteger(1024,DEC);  	// Decimal
 *			writeInteger(044,OCT);		// Ocal
 *			writeInteger(0b11010111,BIN); // Binary
 */
void writeInteger(int16_t number, uint8_t base)
{
	char buffer[17];
	itoa(number, &buffer[0], base);
	writeString(&buffer[0]);
}

/**
 * Same as writeInteger, but with defined length.
 * This means this routine will add leading zeros to the number if length is
 * larger than the actual value or cut the upper digits if length is smaller
 * than the actual value.
 *
 * Example:
 *
 *			// Write a hexadecimal number to the UART:
 *			writeIntegerLength(0xAACC, 16, 8);
 *			// Instead of 16 you can also write "HEX" as this is defined in the
 *			// RP6RobotBaseLib.h :
 *			writeIntegerLength(0xAACC, HEX, 8);
 *			// Other Formats:
 *			writeIntegerLength(1024,DEC,6);  	// Decimal
 *			writeIntegerLength(044,OCT,4);		// Ocal
 *			writeIntegerLength(0b11010111,BIN,8); // Binary
 */
void writeIntegerLength(int16_t number, uint8_t base, uint8_t length)
{
	char buffer[17];
	itoa(number, &buffer[0], base);
	int8_t cnt = length - strlen(buffer);
	if(cnt > 0) {
		for(; cnt > 0; cnt--, writeChar('0'));
		writeString(&buffer[0]);
	}
	else 
		writeStringLength(&buffer[0],length,-cnt);
}

/*****************************************************************************/
// UART receive functions:

// MAXIMUM Buffer size is 254.
volatile char uart_receive_buffer[UART_RECEIVE_BUFFER_SIZE+1];

volatile uint8_t uart_status;

uint8_t read_pos = 0;
uint8_t write_pos = 0; 
uint8_t read_size = 0;
uint8_t write_size = 0;

/**
 * UART receive ISR.
 * Handles reception to circular buffer.
 */
ISR(USART_RXC_vect)
{	
	static volatile uint8_t dummy;
	if(((uint8_t)(write_size - read_size)) < UART_RECEIVE_BUFFER_SIZE) {
		uart_receive_buffer[write_pos++] = UDR;
		write_size++;
		if(write_pos > UART_RECEIVE_BUFFER_SIZE) 
			write_pos = 0;
		uart_status = UART_BUFFER_OK;
	}
	else {	
		dummy = UDR;
		uart_status = UART_BUFFER_OVERFLOW;
	}
}

/**
 * Read a char from the circular buffer. 
 * The char is removed from the buffer (or more precise: not accessible directly anymore
 * and will be overwritten as soon as new data becomes available)!
 *
 * Example:
 *
 * // [...]
 * if(getBufferLength()) 		
 *	   receivedData[data_position++] = readChar();
 * // [...]
 *
 */
char readChar(void)
{
	uart_status = UART_BUFFER_OK;
	if(((uint8_t)(write_size - read_size)) > 0) {
		read_size++;
		if(read_pos > UART_RECEIVE_BUFFER_SIZE) 
			read_pos = 0;
		return uart_receive_buffer[read_pos++];
	}
	return 0;
}

/**
 * Same as readChar, but this function copies numberOfChars chars from the
 * circular buffer to buf. 
 * It also returns the number of characters really copied to the buffer! 
 * Just in case that there were fewer chars in the buffer...
 */
uint8_t readChars(char *buf, uint8_t numberOfChars)
{
	uint8_t i = 0;
	uart_status = UART_BUFFER_OK;
	while(((uint8_t)(write_size - read_size)) >= numberOfChars) {
		read_size++;
		buf[i++] = uart_receive_buffer[read_pos++];
		if(read_pos > UART_RECEIVE_BUFFER_SIZE) 
			read_pos = 0;
	}
	return i;
}

/**
 * Returns the current number of elements in the buffer.
 *
 * Example:
 * s. readChar function above!
 */
uint8_t getBufferLength(void)
{
	return (((uint8_t)(write_size - read_size)));
}

/**
 * Clears the reception buffer - it disables UART Receive 
 * interrupt for a short period of time. 
 */
void clearReceptionBuffer(void)
{
	static uint8_t dummy;
	UCSRB &= ~(1 << RXCIE); // disable UART RX Interrupt
	dummy = UDR;
	read_pos = 0;
	write_pos = 0; 
	read_size = 0;
	write_size = 0;
	uart_status = UART_BUFFER_OK;
	UCSRB |= (1 << RXCIE); // enable Interrupt again
}

/******************************************************************************
 * Additional info
 * ****************************************************************************
 * Changelog:
 * - v. 1.1 10.09.2007 by Dominik S. Herwald
 *		- REMOVED: Old UART reception functions completely
 *		- NEW: Interrupt based reception with circular buffer
 *		- NEW: Documentation for UART reception
 *		- Side effect of this change is, that several example programs
 *		  including the Selftest program needed to be changed!
 * - v. 1.0 (initial release) 10.04.2007 by Dominik S. Herwald
 *
 * ****************************************************************************
 * Bugs, feedback, questions and modifications can be posted on the AREXX Forum
 * on http://www.arexx.com/forum/ !
 * Of course you can also write us an e-mail to: info@arexx.nl
 * AREXX Engineering may publish updates from time to time on AREXX.com!
 * ****************************************************************************
 * - LICENSE -
 * GNU GPL v2 (http://www.gnu.org/licenses/gpl.txt, a local copy can be found
 * on the RP6 CD in the RP6 sorce code folders!)
 * This program is free software. You can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 * ****************************************************************************
 */

/*****************************************************************************/
// EOF

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -