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

📄 rc_mk1.2.1_tx.c

📁 CYRF6936 based system Receiver & transmiter
💻 C
字号:
// TX/** * \file main.c * \brief Firmware for the CYRF6936 based RC system. * \author Duncan Law * \version main.c V1.2 * * \log. * 01/12/08 v1 firmware complete. * 30/12/08 added check for ACK packet and retransmit if ACK not detected. * 01/10/09 enabled watch dog timer * 01/10/09 added timer0 based timing control. * * * License: See documentation. */ #include "main.h"#include </usr/avr/include/avr/iom2561_dla.h>#include </usr/avr/include/compat/deprecated.h>#include <avr/pgmspace.h>#include <avr/wdt.h>                    // watchdog timer#define NOP asm("nop");#define F_CPU        8000000                            // 8MHz processor#define CYCLES_PER_US ((F_CPU+500000)/1000000)  // cpu cycles per microsecond#define PSclock			7               // PB7  clock. blue#define PSdata			6               // PB6  data. brown#define PScommand		5               // PB5  command. orange#define PSattention		5               // PE5  attention. yellowint main(){    // set the baud rate of the UART   uartSetUp(19200);     UARTout(0x0A);		//newline     UARTout(0x0D);		//newline     UARTout('s');		     UARTout('t');		     UARTout('a');		     UARTout('r');		     UARTout('t');		     UARTout(0x0A);		//newline     UARTout(0x0D);		//newline    short int i; // loop  short int j; // loop  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);   // PSx controller I/O pin setup:   sbi(DDRB, PSclock);                 // clock. output. (blue)   cbi(DDRB, PSdata);                 // data. input. (brown)   sbi(PORTB, PSdata);               //    enable pullup resistor   sbi(DDRB, PScommand);                 // command. output. (orange)   sbi(DDRE, PSattention);                 // attention. output. (yellow)  // 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.  spi_Init_RF();			// setup SPI with RF module settings  initialisePS2();			// setup PS2 controller.   unsigned char tmp;			// read registers at startup to clear.  tmp = SPSR;  tmp = SPDR;  unsigned char CHANNEL_ADR_A = 0x48;  unsigned char CHANNEL_ADR_B = 0x00;  unsigned char RSSI;  unsigned char data[12];  unsigned char PacketType = 0x01;  unsigned char timeL = 0;  unsigned char timeH = 0;  short int PWM_count_total = 0, time_int = 0;  unsigned char chan_num, test_time1;  short int PWM_count, PWM_count_error, PWM_count_consecutive_error_max, PWM_count_consecutive_error, PacketTX_result, PacketTX_debounce;  // setting up RF module....  SpiByteWrite(0x1D,0x01);			// MODE_OVERRIDE, RST (Reset module)  //SpiByteWrite(0x26,0x08);		// XTAL_CFG  (must)  //SpiByteWrite(0x32,0x3C);		// AUTO_CAL_TIME  (must)  //SpiByteWrite(0x35,0x14);		// AUTO_CAL_OFFSET  (must)  SpiByteWrite(0x15,0x14);		// CRC_SEED_LSB  SpiByteWrite(0x16,0x14);		// CRC_SEED_MSB  SpiByteWrite(0x00,0x48);			// CHANNEL. (0x48 is default.)  SpiByteWrite(0x03, 0x2F);			// TX_CFG, set power level  SpiByteWrite(0x06,0x4A);              // RX_CFG_ADR  SpiByteWrite(0x0F,0x83);			// XACT_CFG,END_STATE,ACK EN, ACK_TO_4X  SpiByteWrite(0x10,0xEE);			// FRAMING_CFG, LEN EN  SpiByteWrite(0x11,0x05);			// DATA32_THOLD  SpiByteWrite(0x12,0x0E);			// DATA64_THOLD  SpiByteWrite(0x1B,0x55);			// TX_OFFSET_LSB  //SpiByteWrite(0x1B,0x30);			// TX_OFFSET_LSB  SpiByteWrite(0x1C,0x05);			// TX_OFFSET_MSB  SpiByteWrite(0x24,0x10);			// PREAMBLE  SpiByteWrite(0x24,0x33);			// PREAMBLE  SpiByteWrite(0x24,0x33);			// PREAMBLE  //SpiByteWrite(0x39,0x01);			// ANALOG_CTRL_ADR, ALL SLOW (for GFSK)  // timer0 setup  TCCR0A = 0x00;  TCCR0B = 0x05;				// timer0 prescaler = 1024  TCNT0 = 0x00;					// set timer0 to 0x00.  // watchdog timer reset and enable  wdt_reset();  wdt_enable(0x02);				// reset after 60ms.  while (1) // Loop forever  {     wdt_reset();				// watchdog timer reset     RSSI = SpiByteRead(0x13);			// RSSI read. (initialise)     RSSI = SpiByteRead(0x13);			// RSSI read. (RX signal strength)     readPS2(data);				// finishes on 0x1D.     data[0] = PacketType;     data[1] = RSSI & 0x1F;			// Received power level.     data[2] = 0x07;				// transmit power level. (at both ends)     data[3] = chan_num;			// counter to keep track of chanel changes     data[4] = TCNT0;				// timer0 value to syncronise clocks.     // RF transmit and log any errors:     if(PacketTX_result = PacketTX(data)){	PWM_count_error++;	PWM_count_consecutive_error++;      }     else{	if (PWM_count_consecutive_error > PWM_count_consecutive_error_max){		PWM_count_consecutive_error_max = PWM_count_consecutive_error;	}	PWM_count_consecutive_error = 0;     }     // once per second output transmission statistics.     if (PWM_count++ == 49){		// 50 x 20ms devisions have passed.	if (PWM_count_consecutive_error > PWM_count_consecutive_error_max){		PWM_count_consecutive_error_max = PWM_count_consecutive_error;	}	// 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_consecutive_error_max);	UARTout(',');	UARTout_dec(PWM_count_total/time_int);	UARTout(' ');	UARTout_dec(RSSI & 0x1F);	UARTout(0x0A);	PWM_count=0;	PWM_count_error=0;	PWM_count_consecutive_error = 0;	PWM_count_consecutive_error_max=0;     }     // cycle between channels every 5 cycles.     if (chan_num++ < 5){     	SpiByteWrite(0x00,0x45);		// CHANNEL	//UARTout('A');     }     else if ((chan_num >= 5) && (chan_num <= 10)){	SpiByteWrite(0x00,0x48);		// CHANNEL	//UARTout('B');     }     else{	SpiByteWrite(0x00,0x60);		// CHANNEL	//UARTout('C');     }     if (chan_num >= 15) { chan_num = 0;}     // pause untill end of 20ms cycle.     while (TCNT0 < 0x97){}     TCNT0 = 0x00;		//reset system clock.  }}// 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 */	UBRR0H = (unsigned char)(bauddiv>>8);	UBRR0L = (unsigned char)bauddiv;	/* Enable receiver and transmitter */	UCSR0B = (1<<RXEN0)|(1<<TXEN0);	/* Set frame format: 8data, 2stop bit */	UCSR0C = (1<<USBS0)|(3<<UCSZ00);}// send an 8bit number out of the UART.void UARTout(unsigned char data){        while (!(UCSR0A & (1<<UDRE0)))                {                continue;                }        UDR0 = 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;}// 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 ;}// transmit packet on RF module.unsigned char PacketTX(unsigned char *data){     //      unsigned int tmp=0x00;     SpiByteWrite(0x01,0x10);			// TX_LENGTH     SpiByteWrite(0x02,0x40);			// TX_CTRL_ADR, TX_CLR     while(TCNT0 < 0x90){			// retransmit until out of time.	     //SpiByteWrite(0x02,0x40);		// TX_CTRL_ADR, TX_CLR. (do this!)	     SpiByteWrite(0x02,0xC0);		// TX_CTRL_ADR, TX_CLR & TX_GO	     SpiByteWrite(0x20,data[0]);	// 1st byte of TX buffer. (packet type.)     	     SpiByteWrite(0x20,data[1]);     	     SpiByteWrite(0x20,data[2]);     	     SpiByteWrite(0x20,data[3]);     	     SpiByteWrite(0x20,TCNT0);		// timestamp     	     SpiByteWrite(0x20,data[5]);     	     SpiByteWrite(0x20,data[6]);     	     SpiByteWrite(0x20,data[7]);     	     SpiByteWrite(0x20,data[8]);     	     SpiByteWrite(0x20,data[9]);     	     SpiByteWrite(0x20,data[10]);     	     SpiByteWrite(0x20,data[11]);     	     SpiByteWrite(0x20,data[12]);     	     SpiByteWrite(0x20,data[13]);     	     SpiByteWrite(0x20,data[14]);     	     SpiByteWrite(0x20,data[15]);	     tmp=0x00;	     //SpiByteWrite(0x02,0x80);		// TX_CTRL_ADR, TX_GO. Start transmit	     while (!(tmp & (1<<1))){ //&& (TCNT0 < 0x90)){	// wait until write complete		tmp = SpiByteRead(0x04);	// TX_IRQ_STATUS, TXC IRQ	     }	     //UARTout(tmp);      	     if (!(tmp & (1<<0)))  { 			// check TXE (checking for ACK)		if (!(SpiByteRead(0x04) & (1<<0))){	// check TXE again.			//UARTout(1);			return 0;			// ACK came back. no TX errors.		}	     }	     //else { // TX error occured. transmit again}	     // need to put a random length delay in here before repeat	     // to stop bandwidth hogging.	     //delay_us(100);     }     //UARTout(0);     return 1;}void spi_Init_RF(){	// these are the SPI settings needed for the RF module.   	SPCR = _BV(SPE) | _BV(MSTR);		// SPI enable bit and the master mode bit	return;}// PSx controller communication function.// send a byte on the command line and receive one on the data line.// needs Attention pin to have gone low before called to activate controller.int gameByte(short int command){        short int i ;        short int data = 0x00;      // clear data variable to save setting low bits later.        for(i=0;i<8;i++)        {                if(command & _BV(i)) 		    {sbi(PORTB, PScommand);}  // bit bang "command" out on PScommand wire.                else		    cbi(PORTB, PScommand);                cbi(PORTB, PSclock);                    // CLOCK LOW                delay_us(0);                            // wait for output to stabilise                if((PINB & _BV(PSdata))) sbi(data, i);  // read PSdata pin and store                //else cbi(data, i);                sbi(PORTB, PSclock);                    // CLOCK HIGH        }        sbi(PORTB, PScommand);//		**need to check there are no controller read repeats without this delay**//        delay_us(10);                                   // wait for ACK to pass.        return(data);}void initialisePS2(void){   // this loop continues to put PSx controller into analouge mode untill the   // controller responds with 0x73 in the 2nd byte.    // (PS2 controller responds with 0x73 when in analouge mode.)   // the status LEDs will continue to count upwards untill a controller is found.   // if everything is working correctly this should happen on the first pass of   // this loop but occasionally errors occur and a 2nd or 3rd itteration happen.   unsigned char chk_ana = 0, cnt = 0;   while(chk_ana != 0x73){       // put controller in config mode       sbi(PORTB, PScommand);       sbi(PORTB, PSclock);       cbi(PORTE, PSattention);       gameByte(0x01);       gameByte(0x43);       gameByte(0x00);       gameByte(0x01);       gameByte(0x00);       sbi(PORTB, PScommand);       sbi(PORTE, PSattention);       delay_us(1);       // put controller in analouge mode       sbi(PORTB, PScommand);       sbi(PORTB, PSclock);       cbi(PORTE, PSattention);       gameByte(0x01);       gameByte(0x44);       gameByte(0x00);       gameByte(0x01);       gameByte(0x03);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       sbi(PORTB, PScommand);       sbi(PORTE, PSattention);       delay_us(1);       // exit config mode       sbi(PORTB, PScommand);       sbi(PORTB, PSclock);       cbi(PORTE, PSattention);       gameByte(0x01);       gameByte(0x43);       gameByte(0x00);       gameByte(0x00);       gameByte(0x5A);       gameByte(0x5A);       gameByte(0x5A);       gameByte(0x5A);       gameByte(0x5A);       sbi(PORTB, PScommand);       sbi(PORTE, PSattention);       delay_us(1);       // poll controller and check in analouge mode.       sbi(PORTB, PScommand);       sbi(PORTB, PSclock);       cbi(PORTE, PSattention);       gameByte(0x01);       chk_ana = gameByte(0x42);            // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller.       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       gameByte(0x00);       sbi(PORTB, PScommand);       sbi(PORTE, PSattention);       delay_us(1);   }}void readPS2(unsigned char *data){   unsigned char verify = 0;   unsigned char chk = 0;   while ((verify !=0x73)){		// repeat this section untill it works       sbi(PORTB, PScommand);       sbi(PORTB, PSclock);       cbi(PORTE, PSattention);       gameByte(0x01);       verify = gameByte(0x42);       gameByte(0x00);       data[6] = gameByte(0x00);       data[7] = gameByte(0x00);       data[8] = gameByte(0x00);       data[9] = gameByte(0x00);       data[10] = gameByte(0x00);       data[11] = gameByte(0x00);       data[12] = chk++;		// keep count of number of repeats       sbi(PORTB, PScommand);       sbi(PORTE, PSattention);    }    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 < 10; i++) {delay_us(100);}	return;}

⌨️ 快捷键说明

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