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

📄 rp6controllib.c

📁 RP6机器人范例程序。包括移动
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Example:
 *
 *			// Write a hexadecimal number to the LCD:
 *			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(511,OCT);		// Ocal
 *			writeInteger(0b11010111,BIN); // Binary
 */
void writeIntegerLCD(int16_t number, uint8_t base)
{
	itoa(number, &lcd_tmp_buffer[0], base);
	writeStringLCD(&lcd_tmp_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 LCD:
 *			writeIntegerLength(0xAACC, 16, 8);
 *			// Instead of 16 you can also write "HEX" as this is defined in the
 *			// RP6ControlLib.h :
 *			writeIntegerLength(0xAACC, HEX, 8);
 *			// Other Formats:
 *			writeIntegerLength(1024,DEC,6);  	// Decimal
 *			writeIntegerLength(511,OCT,4);		// Ocal
 *			writeIntegerLength(0b11010111,BIN,8); // Binary
 */
 
void writeIntegerLengthLCD(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--, writeCharLCD('0'));
		writeStringLCD(&buffer[0]);
	}
	else 
		writeStringLengthLCD(&buffer[0],length,-cnt);
}

/**
 * This function is useful for displaying text screens on the LCD.
 * It clears the whole LCD and writes the two Strings to line 1 and
 * line 2.
 */
void _showScreenLCD_P(const char *line1, const char *line2)
{
	clearLCD();
	writeNStringLCD_P(line1);
	setCursorPosLCD(1, 0);
	writeNStringLCD_P(line2);
}

/**
 * Sets the cursor position on LCD.
 */
void setCursorPosLCD(uint8_t line, uint8_t pos)
{
	pos |= 128;
	if(line==1) pos += 0x40;
	writeLCDCommand(pos);
}

/**
 * Clears some characters after the given position.
 */
void clearPosLCD(uint8_t line, uint8_t pos, uint8_t length)
{
	setCursorPosLCD(line,pos);
	while(length--)
		writeCharLCD(' ');
}

/*****************************************************************************/
// Keypad:

/**
 * Checks which key is pressed - returns the key number,
 * or 0, if no key is pressed.
 * Maybe you need to adjust these values because of variations
 * in the resitors of the keypad!
 *
 */
uint8_t getPressedKeyNumber(void)
{
	uint16_t keys;
	keys = readADC(ADC_KEYPAD);
	if(keys < 1020) {
		nop();
		nop();
		nop();
		keys += readADC(ADC_KEYPAD);
		keys >>= 1;
	}
	if(keys < 50)
		return 1;
	if(keys < 580)
		return 2;
	if(keys < 700)
		return 3;
	if(keys < 790)
		return 4;
	if(keys < 830)
		return 5;
	return 0;
}

/**
 * This function has to be called frequently out of
 * the main loop and checks if a button is pressed! It only returns 
 * the key number a single time, DIRECTLY when the button is pressed.
 * 
 * This is useful for non-blocking keyboard check in the
 * main loop. You don't need something like 
 * "while(getPressedKeyNumber());" to wait for the button
 * to be released again!
 */
uint8_t checkPressedKeyEvent(void)
{
	static uint8_t pressed_key = 0;
	if(pressed_key) {
		if(!getPressedKeyNumber()) 
			pressed_key = 0;
	}
	else {
		pressed_key = getPressedKeyNumber();
		if(pressed_key)
			return pressed_key;
	}
	return 0;
}

/**
 * This function has to be called frequently out of
 * the main loop and checks if a button is pressed AND
 * released. It only returns the key number a single time, 
 * AFTER the button has been released.
 * 
 * This is useful for non-blocking keyboard check in the
 * main loop. You don't need something like 
 * "while(getPressedKeyNumber());" to wait for the button
 * to be released again!
 */
uint8_t checkReleasedKeyEvent(void)
{
	static uint8_t released_key = 0;
	if(released_key) {
		if(!getPressedKeyNumber()) {
			uint8_t tmp = released_key;
			released_key = 0;
			return tmp;
		}
	}
	else
		released_key = getPressedKeyNumber();
	return 0;
}

/*****************************************************************************/
// Microphone:

/** 
 * This function discharges the Capacitor of the peak detection circuit 
 * used for the Microphone. This is required to remove any previous
 * charge from the capacitor. 
 */
void dischargePeakDetector(void)
{
	DDRA |= MIC;
	PORTA &= ~MIC;
	mSleep(1);
	DDRA &= ~MIC;
}

/**
 * Reads the Microphone peak detector and discharges it afterwards.
 * 
 */
uint16_t getMicrophonePeak(void)
{
	uint16_t tmp;
	tmp = readADC(ADC_MIC);
	if(tmp > 4) 
		dischargePeakDetector();
	return tmp;
}

/*****************************************************************************/
// Delays, Stopwatches and Beeper:


// ---------------------
// Internal status bits
volatile union {
	uint8_t byte;
	struct {
		unsigned beep:1;
		unsigned unused:7;
	};
} controlStatus;

volatile stopwatches_t stopwatches;
volatile uint8_t delay_timer;
volatile uint8_t ms_timer;
volatile uint16_t sound_timer;

volatile uint16_t timer; // You can use this timer for everything you like!


/**
 * Timer 0 Compare ISR - This timer is used for various
 * timing stuff: The delay timer for blocking delays, 
 * "Stopwatches" for non-blocking delays and the timing of
 * the sound generation with timer2...
 *
 * By default, it runs at 10kHz which means this ISR is called
 * every ~100祍! This is nice for timing stuff!
 */
ISR (TIMER0_COMP_vect)
{
	// 16bit timer (100祍 resolution)
	timer++;
	
	// Blocking delay (100祍):
	delay_timer++;
	
	// All 1ms based timing stuff
	if(ms_timer++ >= 10) { // 10 * 100祍 = 1ms
		// 16bit Stopwatches:
		if(stopwatches.watches & STOPWATCH1)
			stopwatches.watch1++;
		if(stopwatches.watches & STOPWATCH2)
			stopwatches.watch2++;
		if(stopwatches.watches & STOPWATCH3)
			stopwatches.watch3++;
		if(stopwatches.watches & STOPWATCH4)
			stopwatches.watch4++;
		if(stopwatches.watches & STOPWATCH5)
			stopwatches.watch5++;
		if(stopwatches.watches & STOPWATCH6)
			stopwatches.watch6++;
		if(stopwatches.watches & STOPWATCH7)
			stopwatches.watch7++;
		if(stopwatches.watches & STOPWATCH8)
			stopwatches.watch8++;

		// Sound generation timing:
		if(controlStatus.beep) {
			if(sound_timer < 1) { // sound_timer * 1ms
				TCCR2 = 0;
				controlStatus.beep = false;
			}
			else
				sound_timer--;
		}
		
		ms_timer = 0;
	}
}


/**
 * You can use this function to make the beeper beep ;) 
 * But this function should not be used as it does not
 * generate a delay for the sound and a delay between 
 * two sounds. Better is to use the "sound" macro, which
 * uses this function and adds the required delays.
 *
 * "sound(pitch,time,delay)"
 *
 * 0 = lowest frequency
 * 255 = highest frequency
 *
 * Example:
 * sound(150,50,25);
 * sound(200,50,25);
 *
 * Of course the function "beep" is nice to generate
 * sounds when you need to do other things at the same
 * time... 
 */
void beep(uint8_t pitch, uint16_t time)
{
	controlStatus.beep = true;
	sound_timer = time;
	OCR2 = 255-pitch;
	TCCR2 =  (1 << WGM21) | (1 << COM20) | (1 << CS22) | (1 << CS21);
}

/**
 * This function has no timing stuff, but otherwise
 * it has the same effect as "beep". It only sets the pitch
 * and this can be used to generate tone sequences which
 * would sound bad if the beeper turns of for a very short time
 * in between - such as alarm tones or special melodies etc. 
 */
void setBeeperPitch(uint8_t pitch)
{
	controlStatus.beep = false;
	OCR2 = 255-pitch;
	if(pitch) 
		TCCR2 =  (1 << WGM21) | (1 << COM20) | (1 << CS22) | (1 << CS21);	
	else 
		TCCR2 = 0;
}

/**
 * Delay with the help of the 10kHz timer.
 * sleep(10) delays for *about* 1ms! Not exaclty, as we do not use assembly routines
 * anywhere in this library!
 *
 * This is a blocking routine, which means that the processor
 * will loop in this routine and (except for interrupts) the
 * normal program flow is stopped!
 * Thus you should use the Stopwatch functions wherever you can!
 *
 * Example:
 *		sleep(1); // delay 1 * 100us = 100us = 0.1ms
 *		sleep(10); // delay 10 * 100us = 1000us = 1ms
 *		sleep(100); // delay 100 * 100us = 10000us = 10ms
 *		// The maximum delay is:
 *		sleep(255); // delay 255 * 100us = 25500us = 25.5ms
 */
void sleep(uint8_t time)
{
	delay_timer = 0;
	while (delay_timer <= time+1);
}

/**
 * The same as sleep() but this delays for time*1ms.
 *
 * Example:
 *      mSleep(100); // delay 100 * 1ms = 100ms = 0.1s
 *		mSleep(1000); // delay 1000 * 1ms = 1000ms = 1s
 *
 */
void mSleep(uint16_t time)
{
	while (time--) sleep(10);
}

/**
 * Delay a number of instruction cycles. 
 * No exact delay function! And interrupts can still occur and 
 * add a lot of extra cycles.
 * This function only guarantees to delay for a MINIMAL number
 * of cycles! 
 *
 * Example:
 * 	delayCycles(1000); // Delays for *about* 1000 instruction cycles
 */
void delayCycles(uint16_t dly)
{
	while(dly--) nop();
}


/*****************************************************************************/
// Initialisation:

/**
 * Initialize the Controller - ALWAYS CALL THIS FIRST!
 * The Processor will not work correctly otherwise.
 * (If you don't implement your own init routine...)
 *
 * Example:
 *
 *			int main(void)
 *			{
 *				initRP6Control(); // CALL THIS FIRST!
 *
 *				// ... your application code
 *
 *				while(true);
 *				return 0;
 *			}
 *
 */
void initRP6Control(void)
{
	portInit();		// Setup port directions and initial values.
					// This is the most important step!

	cli();			// Disable global interrupts.

	// UART:
	UBRRH = UBRR_BAUD_LOW >> 8;	// Setup UART: Baud is Low Speed
	UBRRL = (uint8_t) UBRR_BAUD_LOW;
	UCSRA = 0x00;
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
	
	// Initialize ADC:
	ADMUX = 0; //external reference 
	ADCSRA = (0<<ADIE) | (0<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF);
	SFIOR = 0;

	// Initialize External interrupts - all disabled:
	MCUCR = (1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00);
	GICR = (0 << INT2) | (0 << INT1) | (0 << INT0);
	MCUCSR = (0 << ISC2);
	
	
	// 10kHz Timer 0:
	TCCR0 =   (0 << WGM00) 
			| (1 << WGM01) 
			| (0 << COM00) 
			| (0 << COM01) 
			| (0 << CS02)  
			| (1 << CS01) 
			| (0 << CS00);
	OCR0  = 199;
	
/*
	Timer 1 is free for your application!
*/

	// Timer 2 - used for beeper:
	TCCR2 =  0; 
	OCR2  = 0xFF; 

	// Enable timer interrupts:
	TIMSK =   (1 << OCIE0); 

	// SPI Master (SPI Mode 0, SCK Frequency is F_CPU/2, which means it is 8MHz 
	// on the RP6 CONTROL M32...):
	SPCR =    (0<<SPIE) 
			| (1<<SPE) 
			| (1<<MSTR) 
			| (0<<SPR0) 
			| (0<<SPR1) 
			| (0<<CPOL) 
			| (0<<CPHA);  
	SPSR = (1<<SPI2X);
	
	sei(); // Enable Global Interrupts
}

/******************************************************************************
 * Additional info
 * ****************************************************************************
 * Changelog:
 * - v. 1.1 by Dominik S. Herwald
 *		- NEW: universal timer variable with 100祍 resolution added!
 * - v. 1.0 (initial release) 16.05.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 + -