/* --------------------------------------------- //ad0x0 mpu6050 * ---------------------------------------------- */ //#include "stm8s_conf.h" //#include "stm8s_delay.h" //#include "i2c_master_poll.h" #include "../i2c/ad0x0_i2c2.h" #include "../i2c/ad0x0_i2c_ext.h" #include #include "mpu6050.h" #include "mpu6050_r.h" #include "../admisc/ad0x0_timman.h" volatile u8 mpu6050_adq_byte=0; static ad0x0_gyrodata_s gdata14,gdata_be,gdata_le;//be==BigEndian static bool g_gyro_tick=false; static volatile uint32_t last_update_tick=0; static uint8_t zavis=0; /*#define MPU6050_POWER_Pin GPIO_PIN_1 #define MPU6050_POWER_GPIO_Port GPIOB*/ void mpu6050_writebits(uint8_t _reg, uint8_t _or_bits, uint8_t _and_mask); /* было дело, лечил зависания методом выключить\включить... void power_set(bool _isOn){ #ifdef MPU6050_POWER_GPIO_Port HAL_GPIO_WritePin(MPU6050_POWER_GPIO_Port,MPU6050_POWER_Pin,_isOn ? GPIO_PIN_SET : GPIO_PIN_RESET); #endif }*/ static uint32_t get_per_ms(uint32_t _tick_start){ uint32_t t=(HAL_GetTick()<_tick_start) ?((uint64_t)HAL_GetTick()+UINT32_MAX-_tick_start) :(HAL_GetTick()-_tick_start); return t; } uint8_t mpu6050_wakeup(){ if(get_per_ms(last_update_tick)>300){ zavis=true; return 1;//выпилиться } return 0;//не выпиливаться из менеджера тиков } void mpu6050_stop(void){ ad0x0_timman_remove(mpu6050_wakeup); g_gyro_tick=false; zavis=false; } ad0x0_gyrodata_s *mpu6050_get_gyrodata_s(void){ return &gdata_be; } //ad0x0_gyrodata_s *mpu6050_get_gyrodata_s_le(void){ return &gdata_le;} enum{ xMPU6050_P_OFF, xMPU6050_P_ON, xMPU6050_START }; void cb_mpu5060_power_set(uint8_t _sf_id,ad0x0_i2c_desc_s *pdi2c,void *p_i2c_ext_t){ // ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t; switch(_sf_id){ /*case xMPU6050_P_OFF: power_set(0); break; case xMPU6050_P_ON: power_set(1); break;*/ case xMPU6050_START: g_gyro_tick=true; zavis=false; last_update_tick=HAL_GetTick(); //ad0x0_timman_add(10,mpu6050_wakeup);перенес в инит, виснет при инициализации сука break; } } void mpu6050_start(void){ ad0x0_i2c2_push_ext_setfunc(xMPU6050_START,cb_mpu5060_power_set); } void mpu6050_on_i2c_err(void){ mpu6050_stop(); } void mpu6050_on_i2c_restart(void){ mpu6050_init(); mpu6050_start(); } void mpu6050_init(void){ /*power_set(false); HAL_Delay(200); power_set(true); HAL_Delay(100);*/ ad0x0_i2c2_set_restart_func(mpu6050_on_i2c_err,mpu6050_on_i2c_restart); ad0x0_timman_add(10,mpu6050_wakeup); // ad0x0_i2c2_push_ext_setfunc(xMPU6050_P_OFF, cb_mpu5060_power_set); // ad0x0_i2c2_push(ADQ_DELAY_MS,250); // ad0x0_i2c2_push_ext_setfunc(xMPU6050_P_ON, cb_mpu5060_power_set); // ad0x0_i2c2_push(ADQ_DELAY_MS,250); mpu6050_writebits(MPU6050_RA_PWR_MGMT_1,0,~(1<_p_post_cb_func = cb_write_register_bit2; } static void cb_write_register_bit2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){ ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t; /*пост процесс команды чтения*/ uint8_t value = (uint8_t)(p_ext->user_data1 & 0xFF);//прочитанный байт uint8_t reg = p_ext->user_data0 & 0xFF; value &= (uint8_t)(p_ext->user_data0>>24);//_and_mask value |= (uint8_t)(p_ext->user_data0>>16);//_or_bits //модифицируем ячейку под следующую команду p_ext->user_data0 = (uint32_t)value<<8 | (uint32_t)reg; p_ext->pbuf_count=2;//уже 2 байта пишим: рег, знач. p_ext->_p_post_cb_func = NULL; } void mpu6050_writebits(uint8_t _reg, uint8_t _or_bits, uint8_t _and_mask){ /*ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W); ad0x0_i2c2_push(ADQ_TX,_reg); ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R);*/ uint8_t h_ext; ad0x0_i2c_ext_t *p_ext_t=NULL; ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди //дальше полный изврат p_ext_t->addr_w=MPU6050_ADDRESS_W; p_ext_t->addr_r=MPU6050_ADDRESS_R; p_ext_t->user_data0=_reg | (uint32_t)0xFF00 | (uint32_t)_or_bits<<16 | (uint32_t)_and_mask<<24; p_ext_t->_p_post_cb_func = cb_write_register_bit; p_ext_t->pbuf_count=1; p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!! p_ext_t->pbuf_rx=(uint8_t*)&p_ext_t->user_data1;//RX!!! p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c; p_ext_t->reference_count=2;//после 3й команды высвободится... вроде... механизм тупой, но хоть что-то ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_SEQ_FIRST_EXT,h_ext); ad0x0_i2c2_push(ADQ_HAL_ADDR_RX_BUF_SEQ_LAST_EXT,h_ext); ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_STOP_EXT,h_ext); } void mpu6050_writebyte(u8 _reg,u8 _byte){ /* ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W); ad0x0_i2c2_push(ADQ_TX,_reg); ad0x0_i2c2_push(ADQ_TX_STOP,_byte); */ uint8_t h_ext; ad0x0_i2c_ext_t *p_ext_t=NULL; ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди p_ext_t->addr_w=MPU6050_ADDRESS_W; p_ext_t->user_data0=_reg | (uint32_t)(_byte<<8); p_ext_t->pbuf_count=2; p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!! p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c; ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_STOP_EXT,h_ext); } /*void mpu6050_readbyte(u8 _reg){ ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W); ad0x0_i2c2_push(ADQ_TX,_reg); ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R); ad0x0_i2c2_push(ADQ_RX_STOP,(u8)mpu6050_adq_byte); }*/ static void cb_mpu6050_readbytes2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t); static void cb_mpu6050_readbytes(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){ ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t; p_ext->pbuf_count=p_ext->user_data1; p_ext->_p_post_cb_func = cb_mpu6050_readbytes2; //refcount больше тут не инкрементируем чтобы все релизилось правильно } static void cb_mpu6050_readbytes2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){ //ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t; //раз мы тут, то все прочиталось, иначе бы была перезагрузка матр.. очереди #define AD0X0_6050_LE_SWAP(X,Y) X = ((uint16_t)Y >> 8)|((uint16_t)Y << 8); memcpy(&gdata_le,&gdata14,sizeof(ad0x0_gyrodata_s)); //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s)); AD0X0_6050_LE_SWAP(gdata_be.ax,gdata_le.ax); AD0X0_6050_LE_SWAP(gdata_be.ay,gdata_le.ay); AD0X0_6050_LE_SWAP(gdata_be.az,gdata_le.az); AD0X0_6050_LE_SWAP(gdata_be.gx,gdata_le.gx); AD0X0_6050_LE_SWAP(gdata_be.gy,gdata_le.gy); AD0X0_6050_LE_SWAP(gdata_be.gz,gdata_le.gz); } //void mpu6050_readbytes(u8 _reg,u8 *_pbuf,u8 _count){//ломаем универсальность.. см. ниже /*расклад такой, эта скотина иногда зависает и мы ее перезагружаем. Это не мешает начитать в буфер всякой херни, по этому делаем вот что: читаем 1) в gdata14 то, что идет с шины, 2) __если__ все прочиталось нормально, то согласно моему плану, вызовется cb_mpu6050_readbytes2. И там уже переворачиваем байты для big endian представления*/ void mpu6050_read14(void){ uint8_t h_ext; ad0x0_i2c_ext_t *p_ext_t=NULL; ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди p_ext_t->addr_w=MPU6050_ADDRESS_W; p_ext_t->addr_r=MPU6050_ADDRESS_R; p_ext_t->user_data0=MPU6050_RA_ACCEL_XOUT_H; p_ext_t->user_data1=14;//_count; p_ext_t->_p_post_cb_func = cb_mpu6050_readbytes; p_ext_t->pbuf_count=1;//1 - это адрес регистра, кол-во байт чтения выставим в колбэке p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!! p_ext_t->pbuf_rx=(uint8_t*)&gdata14;//RX!!! p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c; p_ext_t->reference_count=1; ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_SEQ_FIRST_EXT,h_ext); ad0x0_i2c2_push(ADQ_HAL_ADDR_RX_BUF_SEQ_LAST_EXT,h_ext); /* ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W); ad0x0_i2c2_push(ADQ_TX,_reg); ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R); ad0x0_i2c2_push_rx_pbuf_stop_ext(NULL,_pbuf,_count);*/ } /*#define AD0X0_6050_LE_SWAP(X,Y) X = ((uint16_t)Y >> 8)|((uint16_t)Y << 8); static void mpu6050_damn_lendian(void){ //gdata.ax=(gdata.ax >> 8)|(gdata.ax << 8); memcpy(&gdata_le,&gdata,sizeof(ad0x0_gyrodata_s)); //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s)); AD0X0_6050_LE_SWAP(gdata_be.ax,gdata_le.ax); AD0X0_6050_LE_SWAP(gdata_be.ay,gdata_le.ay); AD0X0_6050_LE_SWAP(gdata_be.az,gdata_le.az); AD0X0_6050_LE_SWAP(gdata_be.gx,gdata_le.gx); AD0X0_6050_LE_SWAP(gdata_be.gy,gdata_le.gy); AD0X0_6050_LE_SWAP(gdata_be.gz,gdata_le.gz); //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s)); }*/ void cb_mpu5060_upd_data(uint8_t _sf_id,ad0x0_i2c_desc_s *pdi2c,void *p_i2c_ext_t){ //mpu6050_damn_lendian(); перенес в mpu6050_read14.cb_mpu6050_readbytes2 extern void ad0x0_gyro_datareaded_cb(void); ad0x0_gyro_datareaded_cb(); } void update_gdata(void){ if(ad0x0_i2c2_is_queue_ready()){ mpu6050_read14(); ad0x0_i2c2_push_ext_setfunc(0,cb_mpu5060_upd_data); last_update_tick=HAL_GetTick(); }else{ /*ошибка периода следования: это когда мы считываем текущие значения, и приходит очередное прерывание*/ __ASM("nop"); } } uint32_t mpu6050_get_last_update_tick(void){ return last_update_tick; } uint8_t mpu6050_zavis(void){ zavis=get_per_ms(last_update_tick)>300; return zavis; } #define AD_GYRO_EVMAX 2; //int g_gyro_evmax=10; void mpu6050_pin_irq(void){ if(g_gyro_tick){ update_gdata(); } }