From 30cb13cf49931f58e13ab4ca054fa37da7653b0b Mon Sep 17 00:00:00 2001 From: Lennart Eriksson Date: Tue, 27 Sep 2016 11:35:07 +0200 Subject: [PATCH] Intermediate storage point --- UAV-ControlSystem/inc/drivers/I2C.h | 27 +- UAV-ControlSystem/src/drivers/I2C.c | 125 +++++--- UAV-ControlSystem/src/drivers/i2c_test.c | 297 ++++++++++++++++++ UAV-ControlSystem/src/main.c | 99 +++--- .../HAL_Driver/Inc/stm32f4xx_hal_conf.h | 2 +- .../HAL_Driver/Src/stm32f4xx_hal_i2c.c | 3 +- 6 files changed, 468 insertions(+), 85 deletions(-) create mode 100644 UAV-ControlSystem/src/drivers/i2c_test.c diff --git a/UAV-ControlSystem/inc/drivers/I2C.h b/UAV-ControlSystem/inc/drivers/I2C.h index aed20ad..07750b3 100644 --- a/UAV-ControlSystem/inc/drivers/I2C.h +++ b/UAV-ControlSystem/inc/drivers/I2C.h @@ -10,10 +10,33 @@ #include "stm32f4xx.h" +/****************************************************************************** +* BRIEF: Configure the I2C bus to be used * +* INFORMATION: * +******************************************************************************/ +void i2c_configure(I2C_TypeDef* i2c, uint16_t sda_pin, uint16_t scl_pin, uint32_t my_address); -void i2c_configure(void); - +/****************************************************************************** +* BRIEF: Get data over the I2C bus * +* INFORMATION: * +* Since this system uses a 7 bit addressing mode we send the slave address * +* in the first bytes 7 MSbs and then the LSb is set to 1 indicating that * +* it is a receive command, after that the slave responds with a 1 bit ack and * +* the data is sent one byte at a time with an acknowledge in between * +* every byte, as per the standard. Returns true if successful * +******************************************************************************/ +bool i2c_receive(uint8_t slave_address, uint8_t* buffer, uint32_t length); +/****************************************************************************** +* BRIEF: Send data over the I2C bus * +* INFORMATION: * +* Since this system uses a 7 bit addressing mode we send the slave address * +* in the first bytes 7 MSbs and then the LSb is set to 0 indicating that * +* it is a send command, after that the slave responds with a 1 bit ack and * +* the data is sent one byte at a time with an acknowledge in between * +* every byte, as per the standard. Returns true if successful * +******************************************************************************/ +bool i2c_send(uint8_t slave_address, uint8_t* data, uint32_t length); #endif /* DRIVERS_I2C_H_ */ diff --git a/UAV-ControlSystem/src/drivers/I2C.c b/UAV-ControlSystem/src/drivers/I2C.c index c2216ec..c93dd0a 100644 --- a/UAV-ControlSystem/src/drivers/I2C.c +++ b/UAV-ControlSystem/src/drivers/I2C.c @@ -7,50 +7,93 @@ #include "drivers/I2C.h" +// the I2C handle sending data over +I2C_HandleTypeDef I2C_handle; - - -void i2c_configure(uint32_t channel) +/****************************************************************************** +* BRIEF: Configure the I2C bus to be used * +* INFORMATION: * +******************************************************************************/ +void i2c_configure(I2C_TypeDef* i2c, uint16_t sda_pin, uint16_t scl_pin, uint32_t my_address) { + uint8_t i2c_af; + // get the correct alternate function for the selected I2C + if(i2c == I2C1) + i2c_af = GPIO_AF4_I2C1; + else if(i2c == I2C2) + i2c_af = GPIO_AF4_I2C2; + else if(i2c == I2C3) + i2c_af = GPIO_AF4_I2C3; + else + i2c_af = GPIO_AF4_I2C1; + + + + //Initialize pins for SCL and SDA GPIO_InitTypeDef GPIO_InitStruct; - I2C_InitTypeDef I2C_InitStruct; + __HAL_RCC_I2C1_CLK_ENABLE(); + __GPIOB_CLK_ENABLE(); + GPIO_InitStruct.Pin = sda_pin | scl_pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = i2c_af; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - // enable APB1 peripheral clock for I2C1 - RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); - // enable clock for SCL and SDA pins - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); - - /* setup SCL and SDA pins - * You can connect I2C1 to two different - * pairs of pins: - * 1. SCL on PB6 and SDA on PB7 - * 2. SCL on PB8 and SDA on PB9 - */ - GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // we are going to use PB6 and PB7 - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // set pins to alternate function - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; // set GPIO speed -// GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // set output to open drain --> the line has to be only pulled low, not driven high - GPIO_InitStruct.Pull = GPIO_PULLUP; // enable pull up resistors - GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; - GPIO_Init(GPIOB, &GPIO_InitStruct); // init GPIOB - - I2C_InitStruct.ClockSpeed = 100000; - I2C_InitStruct.DualAddressMode = - - // Connect I2C1 pins to AF - GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); // SCL - GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA - - // configure I2C1 - I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz - I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; // I2C mode - I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard - I2C_InitStruct.I2C_OwnAddress1 = 0x00; // own address, not relevant in master mode - I2C_InitStruct.I2C_Ack = I2C_Ack_Disable; // disable acknowledge when reading (can be changed later on) - I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses - I2C_Init(I2C1, &I2C_InitStruct); // init I2C1 - - // enable I2C1 - I2C_Cmd(I2C1, ENABLE); + //Initialize I2C communication + I2C_handle.Instance = i2c; + I2C_handle.Init.ClockSpeed = 100000; + I2C_handle.Init.DutyCycle = I2C_DUTYCYCLE_2; + I2C_handle.Init.OwnAddress1 = my_address; + I2C_handle.Init.OwnAddress2 = 0; + I2C_handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + I2C_handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + I2C_handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + I2C_handle.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE; + HAL_I2C_Init(&I2C_handle); +} + + +/****************************************************************************** +* BRIEF: Get data over the I2C bus * +* INFORMATION: * +* Since this system uses a 7 bit addressing mode we send the slave address * +* in the first bytes 7 MSbs and then the LSb is set to 1 indicating that * +* it is a receive command, after that the slave responds with a 1 bit ack and * +* the data is sent one byte at a time with an acknowledge in between * +* every byte, as per the standard. Returns true if successful * +******************************************************************************/ +bool i2c_receive(uint8_t slave_address, uint8_t* buffer, uint32_t length) +{ + uint8_t i = 0; + while(HAL_I2C_Master_Receive(&I2C_handle, (slave_address << 1) | 1, buffer, length, 1000)!= HAL_OK && i++ < 10) + {} + while (HAL_I2C_GetState(&I2C_handle) != HAL_I2C_STATE_READY) + {} + + return (i < 10); +} + +/*************************************************************************** +* BRIEF: Send data over the I2C bus * +* INFORMATION: * +* Since this system uses a 7 bit addressing mode we send the slave address * +* in the first bytes 7 MSbs and then the LSb is set to 0 indicating that * +* it is a send command, after that the slave responds with a 1 bit ack and * +* the data is sent one byte at a time with an acknowledge in between * +* every byte, as per the standard. Returns true if successful * +***************************************************************************/ +bool i2c_send(uint8_t slave_address, uint8_t* data, uint32_t length) +{ + uint8_t i = 0; + // try to send the data 10 times and if no acknowledge is received during these 10 messages we stop trying so that + // the system don't gets stuck forever because a slave is unreachable + while(HAL_I2C_Master_Transmit(&I2C_handle,(slave_address << 1), (uint8_t*)data, length, 1000) != HAL_OK && i++ < 10) + {} + + //Wait til the I2C bus is done with all sending + while (HAL_I2C_GetState(&I2C_handle) != HAL_I2C_STATE_READY){} + + return (i < 10); } diff --git a/UAV-ControlSystem/src/drivers/i2c_test.c b/UAV-ControlSystem/src/drivers/i2c_test.c new file mode 100644 index 0000000..dca5bc6 --- /dev/null +++ b/UAV-ControlSystem/src/drivers/i2c_test.c @@ -0,0 +1,297 @@ +// +//#include "stm32f4xx.h" +// +////_____ M A C R O S +//#define TRUE 1 +//#define FALSE 0 +//#define F_CPU 4000000UL // 4 MHz external XTAL +//#define SCL_CLOCK 100000L // I2C clock in Hz +//#define ADDR_W 0xEE // Module address write mode +//#define ADDR_R 0xEF // Module address read mode +//#define CMD_RESET 0x1E // ADC reset command +//#define CMD_ADC_READ 0x00 // ADC read command +//#define CMD_ADC_CONV 0x40 // ADC conversion command +//#define CMD_ADC_D1 0x00 // ADC D1 conversion +//#define CMD_ADC_D2 0x10 // ADC D2 conversion +//#define CMD_ADC_256 0x00 // ADC OSR=256 +//#define CMD_ADC_512 0x02 // ADC OSR=512 +//#define CMD_ADC_1024 0x04 // ADC OSR=1024 +//#define CMD_ADC_2048 0x06 // ADC OSR=2048 +//#define CMD_ADC_4096 0x08 // ADC OSR=4096 +//#define CMD_PROM_RD 0xA0 // Prom read command +////_____ I N C L U D E S +//#include +////#include +////#include +////#include +//#include +////_____ D E F I N I T I O N S +//unsigned char i2c_start(unsigned char address); +//void i2c_stop(void); +//unsigned char i2c_write( unsigned char data ); +//unsigned char i2c_readAck(void); +//unsigned char i2c_readNak(void); +//void cmd_reset(void); +//unsigned long cmd_adc(char cmd); +//unsigned int cmd_prom(char coef_num); +//unsigned char crc4(unsigned int n_prom[]); +////******************************************************** +////! @brief send I2C start condition and the address byte +////! +////! @return 0 +////******************************************************** +//unsigned char i2c_start(unsigned char address) +//{ +// unsigned char twst; +// +// I2C1->CR1 = 1 << 8 | 1 << 0; +// +// TWCR = (1<>1]) & 0x00FF); +//else n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8); +//for (n_bit = 8; n_bit > 0; n_bit--) +//{ +//if (n_rem & (0x8000)) +//{ +//n_rem = (n_rem << 1) ^ 0x3000; } +//else +//{ +//n_rem = (n_rem << 1); +//} +//} +//} +//n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code +//n_prom[7]=crc_read; // restore the crc_read to its original place +//return (n_rem ^ 0x0); +//} +////******************************************************** +////! @brief main program +////! +////! @return 0 +////******************************************************** +//int main (void) +//{ +//unsigned long D1; // ADC value of the pressure conversion +//unsigned long D2; // ADC value of the temperature conversion +//unsigned int C[8]; // calibration coefficients +//double P; // compensated pressure value +//double T; // compensated temperature value +//double dT; // difference between actual and measured temperature +//double OFF; // offset at actual temperature +//double SENS; // sensitivity at actual temperature +//int i; +//unsigned char n_crc; // crc value of the prom +// +//// setup the ports +//DDRA = 0xFE; +//DDRB = 0x0F; //SPI pins as input +//DDRC = 0x03; // I2C pins as output +//DDRD = 0x82; // RS out and tx out; +// +//PORTA = 0x1F; // I2C pin high +//PORTB = 0xF0; +//PORTC = 0x01; +//PORTD = 0x00; +// +//// initialize the I2C hardware module +//TWSR = 0; // no prescaler +//TWBR = ((F_CPU/SCL_CLOCK)-16)/2; // set the I2C speed +// +//D1=0; +//D2=0; +//cmd_reset(); // reset IC +//for (i=0;i<8;i++){ C[i]=cmd_prom(i);} // read coefficients +//n_crc=crc4(C); // calculate the CRC +//for(;;) // loop without stopping +//{ +//D2=cmd_adc(CMD_ADC_D2+CMD_ADC_4096); // read D2 +//D1=cmd_adc(CMD_ADC_D1+CMD_ADC_4096); // read D1 +//// calcualte 1st order pressure and temperature (MS5607 1st order algorithm) +//dT=D2-C[5]*pow(2,8); +//OFF=C[2]*pow(2,17)+dT*C[4]/pow(2,6); +//SENS=C[1]*pow(2,16)+dT*C[3]/pow(2,7); +// +//T=(2000+(dT*C[6])/pow(2,23))/100; +//P=(((D1*SENS)/pow(2,21)-OFF)/pow(2,15))/100; +//// place to use P, T, put them on LCD, send them trough RS232 interface... +//} +// +//return 0; +//} diff --git a/UAV-ControlSystem/src/main.c b/UAV-ControlSystem/src/main.c index 3368f78..fe16f0b 100644 --- a/UAV-ControlSystem/src/main.c +++ b/UAV-ControlSystem/src/main.c @@ -12,6 +12,7 @@ #include "drivers/adc.h" #include "drivers/system_clock.h" +#include "drivers/I2C.h" #include "stm32f4xx.h" #include "system_variables.h" #include "utilities.h" @@ -28,59 +29,77 @@ int main(void) system_clock_config(); - int i = 1; + +/* COMPAS WORKING + i2c_configure(I2C1, GPIO_PIN_8, GPIO_PIN_9, 0x56); - //Add ADC Channels - adc_pin_add(ADC_CHANNEL_0); - adc_pin_add(ADC_CHANNEL_1); - adc_pin_add(ADC_CHANNEL_12); - //Configure the ADCs - adc_configure(); + uint32_t address = 0b00011110; + uint8_t start_request_1[2] = { 0b00000000, 0b01110000 }; + uint8_t start_request_2[2] = { 0b00000001, 0b10100000 }; + uint8_t start_request_3[2] = { 0b00000010, 0b00000000 }; - /* This is done in system_clock_config for all GPIO clocks */ - //__GPIOB_CLK_ENABLE(); - GPIO_InitTypeDef gpinit; - gpinit.Pin = GPIO_PIN_5; - gpinit.Mode = GPIO_MODE_OUTPUT_PP; - gpinit.Pull = GPIO_PULLUP; - gpinit.Speed = GPIO_SPEED_HIGH; - HAL_GPIO_Init(GPIOB, &gpinit); + uint8_t request_data[1] = { 0b00000110 }; + uint8_t reset_pointer_data[1] = { 0b00000011 }; + uint8_t response_data[6] = { 0x0 }; - adc_start(); - int num = 2000; - int j = 0; - volatile uint32_t time_us[num]; + i2c_send(address, &start_request_1, 2); + i2c_send(address, &start_request_2, 2); + i2c_send(address, &start_request_3, 2); + + // Delay for at least 6 ms for system startup to finish + HAL_Delay(10); while (1) { - i++; + i2c_send(address, &request_data, 1); + i2c_receive(address, &response_data, 6); + i2c_send(address, &reset_pointer_data, 1); - //g_ADCValue = accumulate(g_ADCBuffer,ADC_BUFFER_LENGTH) / ADC_BUFFER_LENGTH; - //HAL_Delay(100); - int g_ADCValue = adc_read(ADC_CHANNEL_0); - int g_ADCValue1 = adc_read(ADC_CHANNEL_1); - int g_ADCValue12 = adc_read(ADC_CHANNEL_12); + // HAL_Delay(100); + if(response_data[0] != 0) + response_data[0] = 0; + } +*/ - int offTime = g_ADCValue; - int onTime = 4096 - offTime; - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5,GPIO_PIN_SET); - for (int i = 0; i < onTime; i++) - { - asm("nop"); - } - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5,GPIO_PIN_RESET); - for (int i = 0; i < offTime; i++) - { - asm("nop"); - } - //Get time in microseconds - if(j < num) - time_us[j++] = clock_get_us(); + i2c_configure(I2C1, GPIO_PIN_8, GPIO_PIN_9, 0x56); + uint32_t address = 0x77; + uint8_t reset_data[1] = { 0x1E }; + + uint8_t init_data[1] = { 0xA2 }; + uint8_t init_rsp_data[2] = { 0x00 }; + + uint8_t request_data[500] = { 0xFF }; + uint8_t response_data[2] = { 0x0 }; + +// while(count--) + i2c_send(address, address, 1); + i2c_send(reset_data[0], &reset_data, 1); + + HAL_Delay(50); + + for(int i = 0; i < 6; i++) + { + if(i2c_send(address, &init_data, 1) == true) + i2c_receive(address, &response_data, 2); + init_data[0] += 2; + } + + + HAL_Delay(20); + + while (1) + { + if(i2c_send(address, &request_data, 1) == true) + i2c_receive(address, &response_data, 2); + +// HAL_Delay(100); + if(response_data[0] != 0) + response_data[0] = 0; } for(;;); diff --git a/revolution_hal_lib/HAL_Driver/Inc/stm32f4xx_hal_conf.h b/revolution_hal_lib/HAL_Driver/Inc/stm32f4xx_hal_conf.h index ecf1646..010c103 100644 --- a/revolution_hal_lib/HAL_Driver/Inc/stm32f4xx_hal_conf.h +++ b/revolution_hal_lib/HAL_Driver/Inc/stm32f4xx_hal_conf.h @@ -392,7 +392,7 @@ * If expr is true, it returns no value. * @retval None */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) + #define assert_param(expr) ((expr) ? (void)0 : a,ssert_failed((uint8_t *)__FILE__ __LINE__)) /* Exported functions ------------------------------------------------------- */ void assert_failed(uint8_t* file, uint32_t line); #else diff --git a/revolution_hal_lib/HAL_Driver/Src/stm32f4xx_hal_i2c.c b/revolution_hal_lib/HAL_Driver/Src/stm32f4xx_hal_i2c.c index 1c0383d..008158e 100644 --- a/revolution_hal_lib/HAL_Driver/Src/stm32f4xx_hal_i2c.c +++ b/revolution_hal_lib/HAL_Driver/Src/stm32f4xx_hal_i2c.c @@ -4763,7 +4763,8 @@ static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uin /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { - if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) + uint32_t time = HAL_GetTick(); + if((Timeout == 0U)||((time - tickstart ) > Timeout)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State= HAL_I2C_STATE_READY;