code:i2c_eeprom
This is an old revision of the document!
I2Cmem.c
#include "i2cmem.h" #ifdef EEPROM //----------General I2C functions------------------------------------------------------------------------- volatile u08 I2Cerr; void init_i2c() { TWBR=(u08)((float)F_CPU/(2*SCL)-8.0); //sets the correct clock rate defined as SCL } //we dont need to enable the hardware - its done in write void i2cstart() { TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //send start while (!(TWCR & (1<<TWINT))); //wait for a start to be transmitted if (((TWSR & 0xF8) != TW_START)&&((TWSR & 0xF8) != TW_REP_START)) I2Cerr|=1; //error } void i2cstop() { TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); while (!(TWCR & (1<<TWSTO))); //wait for stop to be sent } void i2cwrite(u08 c) { TWDR = c; //load the data TWCR = (1<<TWINT)|(1<<TWEN); while (!(TWCR & (1<<TWINT))); //wait for it to be sent if ( ((TWSR & 0xF8) !=TW_MT_SLA_ACK) & ((TWSR & 0xF8) !=TW_MR_SLA_ACK) ) I2Cerr|=2; //error } u08 i2cread(u08 AK) { u16 timeout=1; TWCR=AK; while (!(TWCR & (1<<TWINT)) & timeout) timeout++; //wait for it to be recieved if(!timeout) I2Cerr|=8; //timeout out waiting for data error if((TWSR & 0xF8) !=TW_MR_DATA_ACK) I2Cerr|=4; return TWDR; } //----------EEPROM specific stuff------------------------------------------------------------------------- //Designed for 12 byte records atm void set_address(u32 * address) //Sets an address from a paointer - cannot switch between physical devices { i2cstart(); i2cwrite(SLA_W|(((*address)>>13)&0x08)); //the block i2cwrite((u08)((*address)>>8)); //address write MSB i2cwrite((u08)(*address)); //address write LSB } void write_data(u08 * c, u08 datasize, u32 * address)//The address will be incremented as the data is written { u08 n; //up to 256 bytes can be written at once for(n=0;n<datasize;n++,(*address)++) { if(!((u08)*address)&0xEF) //check the address for overflow for the 7 LSB { i2cstop(); //triggers a page write _delay_loop_2( (u16) ( (float)F_CPU*0.003/4.0 ) );//delay 3 ms for page write set_address(address); //set the new address } i2cwrite(c[n]); //write the data } } void read_data(u08 * destination, u08 datasize, u32 * address)//Reads a block of data from some address { u08 n; datasize--; i2cstart(); i2cwrite(SLA_R|(((*address)>>13)&0x08)); //set read to the correct block for(n=0;n<datasize;n++) { destination[n]=i2cread(_AK_); (*address)++; //increment our pointer if(!(u16)*address) //we reached the end of the block { i2cstop(); set_address(address); } } destination[datasize+1]=i2cread(_NAK_); //send NAK for the last byte recieved } u32 findtop() //Find the address of record number where we enter painted eeprom { u32 top=0; //half way through rounded to nearest 12 u08 n; for(n=17;n;) //start by probing half way through { n--; top+=1<<n; //trial setting of bit top = 12*( (u32) (top/12) ); //round down to nearest 12 set_address(&top); //the probe address if(i2cread(_NAK_)==MAGIC_NUMBER) //see if its painted top-=1<<n; //clear the nth bit } top =12*( (u32) (top/12) ); //make sure our answer is rounded correctly return top; } void painteeprom() //Paints every 12th location with the magic number { u08 magic=MAGIC_NUMBER; //magic is our painting value u32 n=0; for(n=0;n<131072;n+=11) //need to skip 11 bytes between each write location { set_address(&n); //set the eeproms internal address register write_data(&magic,1,&n); //write the data } } #endif
I2Cmem.h
#include "global.h" #include "avrlibdefs.h" #include "avrlibtypes.h" #include "matrix.h" #include "kalman.h" #include "TSIP.h" #include "rprintf.h" #include "i2cmem.h" #include <avr/io.h> #include <stdlib.h> #include <math.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <util/delay_basic.h> #include <avr/eeprom.h> #include <avr/pgmspace.h> #define BAUDRATE (int)9600 //9600 baud for lassen iq #define DELTA_TIME (float)0.02 //20ms #define DELAY _delay_loop_2((u16)((float)F_CPU/(4.0*(float)BAUDRATE))) //delay for suart routine #define SET PORTD |= 0x10 //PORTD.4 is the tx #define CLEAR PORTD &= ~0x10 //kalman filter - NOTE: these constants are airframe specific #define CONTROL_GAIN (float)PI/4.0 //full control input of 1 gives ~ this turn rate #define DAMPING_CONSTANT (float)0.3 //approx how fast oscillations die down as faction per second #define TOP_COUNT (u16)((float)F_CPU*DELTA_TIME/8.0) //timer1 pwm frequency #define PWM_COUNT_TIME (u16)((float)F_CPU*0.0005/8.0) //500us #define I_C -0.001 //control loop #define P_C -0.3 #define D_C -0.5 #define INTEGRAL_LIMIT 0.2/I_C //integral servo shift limited to 1/5 of full scale range #define SCALEHEIGHT (float)(-1.0/160.0) //optimised descent- 1/( atm scale height in 100m units * 2) - http://en.wikipedia.org/wiki/Scale_height #define WEIGHTINGFACTOR (float)(20.0)/(1012000.0)//time to drop 100m at STP/one radian expressed as meters on earth surface #define read_rate (u08)0b10010100 //gyro specific #define read_temp (u08)0b10011100 #define read_melexis (u08)0x80 #define gyro_null 1012 #define altitudelimit 10000 //flight termination conditions #define timelimit 30 //NOTE: for debug #define targeteast (float)(-1.0*Deg2rad) //target waypoint ~ Cambridge #define targetnorth (float)(52.0*Deg2rad) #define Rad2deg 180.0/PI //bloody obvious #define Deg2rad PI/180.0 #define PRINT_COMMA rprintfChar(pgm_read_byte(&comma)) //prints a comma #define battery_factor (float)0.02505 //for measuring battery voltage- checked from test #define battery_chan 0x00 //ADC0 #define toggle_pin PIND=0x20 //led on port D.5 #define BAUDDIV (u16)( ((float)F_CPU/(BAUDRATE*16UL)) -1 )//baud divider #define radio_cts bit_is_set(PIND,2) //hardware, however its wired up #define led_left PORTC = ((PORTC & ~0x0C) | 0x04) #define led_right PORTC = ((PORTC & ~0x0C) | 0x08) #define USER_PRESENT !(PINC&0x02) #define cutter_on PORTD|=(1<<7) //release mechanism (hot resistor off mosfet) #define cutter_off PORTD&=~(1<<7) #define DISABLE_SMPS PORTD|=(1<<6) //turns the SMPS for the servo on/off - never send pwm if its off #define ENABLE_SMPS PORTD&=~(1<<6) #define GYRO_OFF PORTB|=1<<1 //SS line #define GYRO_ON PORTB&=~(1<<1) #ifdef ADCSRA #ifndef ADCSR #define ADCSR ADCSRA #endif #endif #ifdef ADATE #define ADFR ADATE #endif #ifdef GROUND #define enable_ground_control TIMSK1|=(1<<ICIE1) //enables the input capture interrupt #define disable_ground_control TIMSK1&=~(1<<ICIE1) //disables input capture interrupt #define PULSE_MIN 0.001*F_CPU/8 //pwm must be in the range 1 to 2 ms #define PULSE_MAX 0.002*F_CPU/8 #define GROUND_LED_ON PORTD|=(1<<3) #define GROUND_LED_OFF PORTD&=~(1<<3) #define GROUND_LED_SET PORTD&(1<<3) #endif typedef struct { float vup; float vnorth; float veast; float time; float altitude; float longitude; float latitude; u08 packetflag; //packetflag lets us see when our packet has been updated u08 status; u08 nosats; } gps_type; void put_char(unsigned char c); //talk to the UART void suart_send(char c); void run_ground_control(); void _delay_10ms(char time); float driftfactor(int altitude);
code/i2c_eeprom.1225956559.txt.gz · Last modified: 2008/11/06 07:29 by laurenceb