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

📄 rc_mk1.2.1_rx.c

📁 CYRF6936 based system Receiver & transmiter
💻 C
字号:
// RX/** * \file main.c * \brief Firmware for the CYRF6936 based RC system Receiver. * \author Duncan Law * \version receiver/main.c V1.0 * * \log. * \ 01/12/08 v1 of firmware complete. * \ 01/01/09 Restructure of main loop. Now pauses to wait for incoming transmission. * \ 01/01/09 syncronises timer0 according to Controller's timer0 displayed in incoming packet. *  *  * License: See documentation. */#include "main.h"#include <avr/eeprom.h>#include </usr/avr/include/compat/deprecated.h>#define NOP asm("nop");#define F_CPU        8000000                            // 8MHz processor#define CYCLES_PER_US ((F_CPU+500000)/1000000)  // cpu cycles per microsecondint main(){  // timer0 setup for system clock.  TCCR0A = 0x00;  TCCR0B = 0x05;				// timer0 prescaler = 1024  TCNT0 = 0x00;					// set timer0 to 0x00.  // timer1 setup for servo control  TCCR1A = _BV(COM1A1) // set OC1A/B at TOP         | _BV(COM1B1) // clear OC1A/B when match         | _BV(COM1C1)          | _BV(WGM11); // mode 14 (fast PWM, clear TCNT1 on match ICR1)  TCCR1B = _BV(WGM13)         | _BV(WGM12)         | _BV(CS11); // timer uses main system clock with 1/8 prescale  ICR1 = 20000; // used for TOP, makes for 50 hz PWM  OCR1A = 1500; // servo at center  OCR1B = 1500; // servo at center  OCR1C = 1000; // servo at low (ESC off)  DDRB = _BV(PB5)       | _BV(PB6)   // have to set up pins as outputs       | _BV(PB7);  // have to set up pins as outputs  // timer3 setup for servo control  TCCR3A = _BV(COM3A1) // set OC1A/B at TOP         | _BV(COM3B1) // clear OC1A/B when match         | _BV(COM3C1)         | _BV(WGM31); // mode 14 (fast PWM, clear TCNT1 on match ICR1)  TCCR3B = _BV(WGM33)         | _BV(WGM32)         | _BV(CS31); // timer uses main system clock with 1/8 prescale  ICR3 = 20000; // used for TOP, makes for 50 hz PWM  OCR3A = 1500; // servo at center  OCR3B = 1500; // servo at center  OCR3C = 1500; // servo at center  DDRE = _BV(PE3)       | _BV(PE4)   // have to set up pins as outputs       | _BV(PE5);  // have to set up pins as outputs  // set the baud rate of the UART   uartSetUp(19200);  UARTout(0x00);  UARTout(0x00);  UARTout(0x00);  UARTout(0x00);  // setup SPI bus and RF module.  InitialiseRF();  short int timeout = 0;  short int i; 					// loop through data bytes.  unsigned char data[16], data_debounce[16];  unsigned char servo_multiplier = 1;		// multipler for all chanels  float servo_multiplier_1 = 1;			// multiplier for different channels  float servo_multiplier_2 = 1;  uint16_t trimA_addr = 0x0000;  uint16_t trimB_addr = 0x0002;  uint16_t trimA = eeprom_read_word(&trimA_addr);  uint16_t trimB = eeprom_read_word(&trimB_addr);  short int newdata=0;  unsigned char tmp, tmp2, tmp3, TXcount, count;  unsigned char chan_num=0, PWM_count_error=0, PWM_count_consecutive_error_max=0;  short int PWM_count=0, PWM_count_consecutive_error=0, PacketTX_result=0, PacketTX_debounce;  unsigned char timeL = 0;  unsigned char timeH = 0;  short int PWM_count_total = 0, time_int = 0;  TCNT0 = 0x00;					// set timer0 to 0x00.  while (1) // Loop forever  {	while(0){		if ((!(SpiByteRead(0x05) & (1<<7))) && (!(SpiByteRead(0x07) & (1<<6)))){			SpiByteWrite(0x05,0x80); 		    //RX_GO 		}	}     //while(TCNT0 < 0x01){	// Transmitter is reading controller now so this end free to do stuff.     //}     //UARTout_hex(SpiByteRead(0x00));     // put RF module in receive mode:     SpiByteWrite(0x05,0x80); 		    //RX_GO      newdata=0;     // wait for incoming packet.     while((!newdata) && (TCNT0 < 0x95)){	tmp= SpiByteRead(0x07);	if (!(SpiByteRead(0x05))){		tmp2= SpiByteRead(0x08);		if ((tmp & (1<<1)) && (!((tmp) & (1<<0)))){			SpiByteWrite(0x07,0x80);			for (i=0; i<16; i++){		   	//read data.		   		data[i] = SpiByteRead(0x21);			}			TCNT0 = data[4] -4 ;	     // syncronise clocks			newdata=1;			//UARTout('A'); UARTout(0x0A);		}		else {			newdata=0;			/*UARTout('B');			UARTout_hex(tmp);			UARTout(',');			UARTout_hex(tmp2);			UARTout(0x0A);*/		}			}	else {		/*UARTout('C');		UARTout_hex(tmp);		UARTout(',');		UARTout_hex(tmp2);		UARTout(0x0A);*/	}     }     //UARTout(0x0A);     // do something with received packet...//     if (1){     if (newdata ){	 // syncronise which channel Receiver is on. set the same as Controller	 chan_num = data[3];         // top left pad doubles servo movment.         if (!(data[7] & 0x01)) { servo_multiplier = 2; }         else {servo_multiplier = 1;}         // triangle button sets trim.          // data_debounce makes sure only one press is recognised.         if ((!(data[7] & 0x10)) && (data_debounce[7] & 0x10)){	    trimA += - (servo_multiplier*servo_multiplier_2*((2*data[9]) - 255));	    trimB += (servo_multiplier*servo_multiplier_1*((2*data[8]) - 255));	    eeprom_write_word(&trimA_addr, trimA);	    eeprom_write_word(&trimB_addr, trimB);         }         // remember the value of button register on last pass          //so we can compare for single reponse to button press.         data_debounce[7] = data[7];	         // Circle button clears trim         if (!(data[7] & 0x20)) {		    trimA = 0;	    trimB = 0;	    eeprom_write_word(&trimA_addr, trimA);	    eeprom_write_word(&trimB_addr, trimB);         }         // set servos. aerlon controll:         OCR1C = 1900-  (4*data[11]);             // set servo position         OCR1B = 1500+ (servo_multiplier_1*servo_multiplier*((2*data[9]) - 255)) - trimA;         OCR1A = 1500+ (servo_multiplier_2*servo_multiplier*((2*data[8]) - 255)) + trimB;         OCR3C = 1500+ (servo_multiplier_2*servo_multiplier*((2*data[8]) - 255)) + trimB;     }     else{	 PWM_count_error++;     }     // cycle between channels every 5 cycles.     if (chan_num++ < 5){	//UARTout('a');     	SpiByteWrite(0x00,0x45);		// CHANNEL     }     else if ((chan_num >= 5) && (chan_num <= 10)){	//UARTout('b');	SpiByteWrite(0x00,0x48);		// CHANNEL     }     else{	//UARTout('c');	SpiByteWrite(0x00,0x60);		// CHANNEL     }     //UARTout(chan_num);     if (chan_num >= 15) { chan_num = 0;}     if (count++ == 50){	count = 0;	UARTout(TXcount);	TXcount=0;     }     // once per second output transmission statistics.     if (PWM_count++ == 49){            // 50 x 20ms devisions have passed.        // count time in seconds since last power cycle.        time_int++;        timeL++;        if (timeL > 99){                timeH++;                timeL=0;        }        PWM_count_total+=PWM_count_error;        if ((PWM_count_error==50) && (PWM_count_consecutive_error_max==50)){                timeH=0; timeL=0; PWM_count_total=0; PWM_count_error=0;                PWM_count_consecutive_error_max=0; time_int=0;        }        UARTout_dec(timeH);        UARTout_dec(timeL);        UARTout(' ');        UARTout_dec(PWM_count_error);        UARTout(',');        UARTout_dec(PWM_count_total/time_int);        UARTout(0x0A);        PWM_count=0;        PWM_count_error=0;     }     while(TCNT0 < 0x97){}     TCNT0 = 0;  }}// no signal for multiple cycles so reset servo position.void servo_default(uint16_t trimA, uint16_t trimB){	// aerlon control:	OCR1B = 1500 - trimA;	OCR1A = 1500 + trimB;	OCR3C = 1500 + trimB;	OCR1C = 1000;/*	// R/E controll:	OCR1B = 1500 + trimB;	OCR1A = 1500 + trimA;	OCR1C = 1000;*//*	if (OCR1C > 1000){		OCR1C-=0x1;				// center servos,stop motor	}	if (OCR1B > 1503 + trimA){		OCR1B-=0x1;	}	else if (OCR1B < 1497 + trimA){		OCR1B+=0x1;	}	if (OCR1A > 1503 + trimB){		OCR1A-=0x1;	}	else if (OCR1A < 1497 + trimB){		OCR1A+=0x1;	}	if (OCR3C > 1503 + trimB){		OCR3C-=0x1;	}	else if (OCR3C < 1497 + trimB){		OCR3C+=0x1;	}*/     return;}// set the uart baud ratevoid uartSetUp(unsigned int baudrate){        // calculate division factor for requested baud rate, and set it        unsigned int bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);	/* Set baud rate */	UBRR1H = (unsigned char)(bauddiv>>8);	UBRR1L = (unsigned char)bauddiv;	/* Enable receiver and transmitter */	UCSR1B = (1<<RXEN1)|(1<<TXEN1);	/* Set frame format: 8data, 2stop bit */	UCSR1C = (1<<USBS1)|(3<<UCSZ10);}// send an 8bit number out of the UART.// *note* this does not use the pesudo manchester encoding // so many RF modules will not transmit numbers with high proportion of "1"s or "0"s correctly.void UARTout(unsigned char data){        while (!(UCSR1A & (1<<UDRE1)))                {                continue;                }        UDR1 = data;        return;}// send an 8bit number out of the UART. display as decimal number in ASCIIvoid UARTout_dec(unsigned char data){        if(data/100){ UARTout('0' + data/100); }        UARTout('0' + ((data%100)/10));        UARTout('0' + data%10);        return;}// send an 8bit number out of the UART. display as decimal number in ASCIIvoid UARTout_hex(unsigned char data){	if (((data & 0xF0) >= 0) && ((data & 0xF0) < 0xAA)) {	        UARTout('0' + ((data >>4) & 0x0F));	}	else if (((data & 0xF0) >= 0xA0) && ((data & 0xF0) <= 0xF0)){		UARTout('A' + ((data >>4) & 0x0F) - 0x0A);	}	if (((data & 0x0F) >= 0) && ((data & 0x0F) < 0x0A)) {	        UARTout('0' + (data & 0x0F));	}	else if (((data & 0x0F) >= 0x0A) && ((data & 0x0F) <= 0x0F)){		UARTout('A' + (data & 0x0F) - 0x0A);	}        return;}// SPI send byte and receive following byteunsigned char SpiByteRead(unsigned char data){    cbi(PORTB, PB0);			// SS low to initiate SPI.    SPDR = data;			// send byte (Address)    while(!(SPSR & (1<<SPIF)));    SPDR = 0x00;			// not sending anything on the next cycle.    while(!(SPSR & (1<<SPIF)));    sbi(PORTB, PB0);			// SS high to end SPI.    return SPDR;			// receiving data instead.}// SPI send byte and send following bytevoid SpiByteWrite(unsigned char register_address, unsigned char data){    cbi(PORTB, PB0);			// SS low to initiate SPI.    SPDR = register_address | 0x80;	// send byte (Address) with pit 8 set for write enable    while(!(SPSR & (1<<SPIF)));    SPDR = data;			// send byte (data).    while(!(SPSR & (1<<SPIF)));    sbi(PORTB, PB0);			// SS high to end SPI.    return ;}void InitialiseRF(void){  // setup I/O pins connected to RF module.  cbi(DDRE, PE7);                 // set UNIGEN RF module IRQ pin to input  sbi(DDRB, PB0);                 // set UNIGEN RF module SS pin to output  sbi(PORTB, PB0);  sbi(DDRG, PG3);                 // set UNIGEN RF module RST pin to output  cbi(PORTG, PG3);  // set up SPI from: http://www.openavr.org/AVR_SPI_C_Snippets  SPCR = _BV(SPE) | _BV(MSTR);		// SPI enable bit and the master mode bit  DDRB |= _BV(0) | _BV(1) | _BV(2);	// SS is at PB0, SCK is at PB1 and MOSI is at PB2. set direction  PORTB |= _BV(3);			// enable pullups on MISO at PB3.  unsigned char tmp;			// read registers at startup to clear.  tmp = SPSR;  tmp = SPDR;  //SpiByteWrite(0x26,0x08);		// XTAL_CFG  (must)  //SpiByteWrite(0x32,0x3C);		// AUTO_CAL_TIME  (must)  //SpiByteWrite(0x35,0x14);		// AUTO_CAL_OFFSET  (must)  SpiByteWrite(0x1D,0x01);		// MODE_OVERRIDE, RST (Reset module)  SpiByteWrite(0x03,0x2F);		// TX_CFG,   SpiByteWrite(0x05,0x00);		// set RX_CTRL_ADR, RX_GO  SpiByteWrite(0x06,0x4A);		// RX_CFG_ADR, overwrite (RXOW EN)//  SpiByteWrite(0x0F,0x83);		// XACT_CFG, END_STATE & ACK_EN  SpiByteWrite(0x0F,0x93);		// XACT_CFG,END_STATE,ACK EN, ACK_TO_15X  //SpiByteWrite(0x0F,0x11);		// XACT_CFG,END_STATE,ACK EN, ACK_TO_15X//  SpiByteWrite(0x10,0xA4);		// FRAMING_CFG, LEN EN  SpiByteWrite(0x10,0xEE);		// FRAMING_CFG, LEN EN  //SpiByteWrite(0x11,0x05);		// DATA32_THOLD  SpiByteWrite(0x11,0x08);		// DATA32_THOLD  SpiByteWrite(0x12,0x0E);		// DATA64_THOLD  SpiByteWrite(0x15,0x14);		// CRC_SEED_LSB  SpiByteWrite(0x16,0x14);		// CRC_SEED_MSB  SpiByteWrite(0x1B,0x55);		// TX_OFFSET_LSB  SpiByteWrite(0x1C,0x05);		// TX_OFFSET_MSB  SpiByteWrite(0x24,0x10);			// PREAMBLE  SpiByteWrite(0x24,0x33);			// PREAMBLE  SpiByteWrite(0x24,0x33);			// PREAMBLE  //SpiByteWrite(0x1E,0x08);		//   return;}// delay for a minimum of <us> microseconds // the time resolution is dependent on the time the loop takes // e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us void delay_us(unsigned short time_us){        unsigned short delay_loops;        register unsigned short i;        delay_loops = (time_us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty)         // one loop takes 5 cpu cycles         for (i=0; i < delay_loops; i++) {};}void delay_ms(unsigned char time_ms){	unsigned short int i;        for (i=0; i < 500; i++) {delay_us(100);}	return;}

⌨️ 快捷键说明

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