mpu6050.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /* ---------------------------------------------
  2. //ad0x0 mpu6050
  3. * ----------------------------------------------
  4. */
  5. //#include "stm8s_conf.h"
  6. //#include "stm8s_delay.h"
  7. //#include "i2c_master_poll.h"
  8. #include "../i2c/ad0x0_i2c2.h"
  9. #include "../i2c/ad0x0_i2c_ext.h"
  10. #include <string.h>
  11. #include "mpu6050.h"
  12. #include "mpu6050_r.h"
  13. #include "../admisc/ad0x0_timman.h"
  14. volatile u8 mpu6050_adq_byte=0;
  15. static ad0x0_gyrodata_s gdata14,gdata_be,gdata_le;//be==BigEndian
  16. static bool g_gyro_tick=false;
  17. static volatile uint32_t last_update_tick=0;
  18. static uint8_t zavis=0;
  19. /*#define MPU6050_POWER_Pin GPIO_PIN_1
  20. #define MPU6050_POWER_GPIO_Port GPIOB*/
  21. void mpu6050_writebits(uint8_t _reg, uint8_t _or_bits, uint8_t _and_mask);
  22. /*
  23. было дело, лечил зависания методом выключить\включить...
  24. void power_set(bool _isOn){
  25. #ifdef MPU6050_POWER_GPIO_Port
  26. HAL_GPIO_WritePin(MPU6050_POWER_GPIO_Port,MPU6050_POWER_Pin,_isOn ? GPIO_PIN_SET : GPIO_PIN_RESET);
  27. #endif
  28. }*/
  29. static uint32_t get_per_ms(uint32_t _tick_start){
  30. uint32_t t=(HAL_GetTick()<_tick_start)
  31. ?((uint64_t)HAL_GetTick()+UINT32_MAX-_tick_start)
  32. :(HAL_GetTick()-_tick_start);
  33. return t;
  34. }
  35. uint8_t mpu6050_wakeup(){
  36. if(get_per_ms(last_update_tick)>300){
  37. zavis=true;
  38. return 1;//выпилиться
  39. }
  40. return 0;//не выпиливаться из менеджера тиков
  41. }
  42. void mpu6050_stop(void){
  43. ad0x0_timman_remove(mpu6050_wakeup);
  44. g_gyro_tick=false;
  45. zavis=false;
  46. }
  47. ad0x0_gyrodata_s *mpu6050_get_gyrodata_s(void){
  48. return &gdata_be;
  49. }
  50. //ad0x0_gyrodata_s *mpu6050_get_gyrodata_s_le(void){ return &gdata_le;}
  51. enum{
  52. xMPU6050_P_OFF,
  53. xMPU6050_P_ON,
  54. xMPU6050_START
  55. };
  56. void cb_mpu5060_power_set(uint8_t _sf_id,ad0x0_i2c_desc_s *pdi2c,void *p_i2c_ext_t){
  57. // ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t;
  58. switch(_sf_id){
  59. /*case xMPU6050_P_OFF:
  60. power_set(0);
  61. break;
  62. case xMPU6050_P_ON:
  63. power_set(1);
  64. break;*/
  65. case xMPU6050_START:
  66. g_gyro_tick=true;
  67. zavis=false;
  68. last_update_tick=HAL_GetTick();
  69. //ad0x0_timman_add(10,mpu6050_wakeup);перенес в инит, виснет при инициализации сука
  70. break;
  71. }
  72. }
  73. void mpu6050_start(void){
  74. ad0x0_i2c2_push_ext_setfunc(xMPU6050_START,cb_mpu5060_power_set);
  75. }
  76. void mpu6050_on_i2c_err(void){
  77. mpu6050_stop();
  78. }
  79. void mpu6050_on_i2c_restart(void){
  80. mpu6050_init();
  81. mpu6050_start();
  82. }
  83. void mpu6050_init(void){
  84. /*power_set(false);
  85. HAL_Delay(200);
  86. power_set(true);
  87. HAL_Delay(100);*/
  88. ad0x0_i2c2_set_restart_func(mpu6050_on_i2c_err,mpu6050_on_i2c_restart);
  89. ad0x0_timman_add(10,mpu6050_wakeup);
  90. // ad0x0_i2c2_push_ext_setfunc(xMPU6050_P_OFF, cb_mpu5060_power_set);
  91. // ad0x0_i2c2_push(ADQ_DELAY_MS,250);
  92. // ad0x0_i2c2_push_ext_setfunc(xMPU6050_P_ON, cb_mpu5060_power_set);
  93. // ad0x0_i2c2_push(ADQ_DELAY_MS,250);
  94. mpu6050_writebits(MPU6050_RA_PWR_MGMT_1,0,~(1<<MPU6050_PWR1_SLEEP_BIT));
  95. //memset(&gdata,0,sizeof(gdata)); затрет посчитанные данные, пусть остается то шо было
  96. // mpu6050_writebit(MPU6050_RA_PWR_MGMT_1,MPU6050_PWR1_SLEEP_BIT,0);
  97. ad0x0_i2c2_push(ADQ_DELAY_MS,100);
  98. //тут блин ппц
  99. if(1){
  100. mpu6050_writebyte(25,16);//sample rate div=8 (8/24)=0.333 kHz
  101. mpu6050_writebyte(26,0);//filter
  102. }else{
  103. mpu6050_writebyte(25,1);//sample rate div
  104. mpu6050_writebyte(26,6);//filter
  105. }
  106. //
  107. mpu6050_writebyte(0x38,0x9);//прерывания
  108. //mpu6050_readbyte(MPU6050_RA_WHO_AM_I);
  109. //mpu6050_readbytes(MPU6050_RA_ACCEL_XOUT_H,(u8*)&gdata,14);
  110. ad0x0_i2c2_push(ADQ_DELAY_MS,1);
  111. }
  112. //*********************************************************
  113. static void cb_write_register_bit2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t);
  114. static void cb_write_register_bit(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){
  115. ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t;
  116. p_ext->_p_post_cb_func = cb_write_register_bit2;
  117. }
  118. static void cb_write_register_bit2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){
  119. ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t;
  120. /*пост процесс команды чтения*/
  121. uint8_t value = (uint8_t)(p_ext->user_data1 & 0xFF);//прочитанный байт
  122. uint8_t reg = p_ext->user_data0 & 0xFF;
  123. value &= (uint8_t)(p_ext->user_data0>>24);//_and_mask
  124. value |= (uint8_t)(p_ext->user_data0>>16);//_or_bits
  125. //модифицируем ячейку под следующую команду
  126. p_ext->user_data0 = (uint32_t)value<<8 | (uint32_t)reg;
  127. p_ext->pbuf_count=2;//уже 2 байта пишим: рег, знач.
  128. p_ext->_p_post_cb_func = NULL;
  129. }
  130. void mpu6050_writebits(uint8_t _reg, uint8_t _or_bits, uint8_t _and_mask){
  131. /*ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W);
  132. ad0x0_i2c2_push(ADQ_TX,_reg);
  133. ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R);*/
  134. uint8_t h_ext;
  135. ad0x0_i2c_ext_t *p_ext_t=NULL;
  136. ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди
  137. //дальше полный изврат
  138. p_ext_t->addr_w=MPU6050_ADDRESS_W;
  139. p_ext_t->addr_r=MPU6050_ADDRESS_R;
  140. p_ext_t->user_data0=_reg | (uint32_t)0xFF00 | (uint32_t)_or_bits<<16 | (uint32_t)_and_mask<<24;
  141. p_ext_t->_p_post_cb_func = cb_write_register_bit;
  142. p_ext_t->pbuf_count=1;
  143. p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!!
  144. p_ext_t->pbuf_rx=(uint8_t*)&p_ext_t->user_data1;//RX!!!
  145. p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c;
  146. p_ext_t->reference_count=2;//после 3й команды высвободится... вроде... механизм тупой, но хоть что-то
  147. ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_SEQ_FIRST_EXT,h_ext);
  148. ad0x0_i2c2_push(ADQ_HAL_ADDR_RX_BUF_SEQ_LAST_EXT,h_ext);
  149. ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_STOP_EXT,h_ext);
  150. }
  151. void mpu6050_writebyte(u8 _reg,u8 _byte){
  152. /* ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W);
  153. ad0x0_i2c2_push(ADQ_TX,_reg);
  154. ad0x0_i2c2_push(ADQ_TX_STOP,_byte); */
  155. uint8_t h_ext;
  156. ad0x0_i2c_ext_t *p_ext_t=NULL;
  157. ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди
  158. p_ext_t->addr_w=MPU6050_ADDRESS_W;
  159. p_ext_t->user_data0=_reg | (uint32_t)(_byte<<8);
  160. p_ext_t->pbuf_count=2;
  161. p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!!
  162. p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c;
  163. ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_STOP_EXT,h_ext);
  164. }
  165. /*void mpu6050_readbyte(u8 _reg){
  166. ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W);
  167. ad0x0_i2c2_push(ADQ_TX,_reg);
  168. ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R);
  169. ad0x0_i2c2_push(ADQ_RX_STOP,(u8)mpu6050_adq_byte);
  170. }*/
  171. static void cb_mpu6050_readbytes2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t);
  172. static void cb_mpu6050_readbytes(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){
  173. ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t;
  174. p_ext->pbuf_count=p_ext->user_data1;
  175. p_ext->_p_post_cb_func = cb_mpu6050_readbytes2;
  176. //refcount больше тут не инкрементируем чтобы все релизилось правильно
  177. }
  178. static void cb_mpu6050_readbytes2(uint8_t _sf_id,ad0x0_i2c_desc_s *pi2c,void *p_i2c_ext_t){
  179. //ad0x0_i2c_ext_t *p_ext=(ad0x0_i2c_ext_t*)p_i2c_ext_t;
  180. //раз мы тут, то все прочиталось, иначе бы была перезагрузка матр.. очереди
  181. #define AD0X0_6050_LE_SWAP(X,Y) X = ((uint16_t)Y >> 8)|((uint16_t)Y << 8);
  182. memcpy(&gdata_le,&gdata14,sizeof(ad0x0_gyrodata_s));
  183. //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s));
  184. AD0X0_6050_LE_SWAP(gdata_be.ax,gdata_le.ax);
  185. AD0X0_6050_LE_SWAP(gdata_be.ay,gdata_le.ay);
  186. AD0X0_6050_LE_SWAP(gdata_be.az,gdata_le.az);
  187. AD0X0_6050_LE_SWAP(gdata_be.gx,gdata_le.gx);
  188. AD0X0_6050_LE_SWAP(gdata_be.gy,gdata_le.gy);
  189. AD0X0_6050_LE_SWAP(gdata_be.gz,gdata_le.gz);
  190. }
  191. //void mpu6050_readbytes(u8 _reg,u8 *_pbuf,u8 _count){//ломаем универсальность.. см. ниже
  192. /*расклад такой, эта скотина иногда зависает и мы ее перезагружаем. Это
  193. не мешает начитать в буфер всякой херни, по этому делаем вот что:
  194. читаем 1) в gdata14 то, что идет с шины, 2) __если__ все прочиталось нормально, то
  195. согласно моему плану, вызовется cb_mpu6050_readbytes2. И там уже переворачиваем байты
  196. для big endian представления*/
  197. void mpu6050_read14(void){
  198. uint8_t h_ext;
  199. ad0x0_i2c_ext_t *p_ext_t=NULL;
  200. ad0x0_i2c2_get_ext_async2(&h_ext,(void**)&p_ext_t);//получить ячейку, ассоциированную с командой в очереди
  201. p_ext_t->addr_w=MPU6050_ADDRESS_W;
  202. p_ext_t->addr_r=MPU6050_ADDRESS_R;
  203. p_ext_t->user_data0=MPU6050_RA_ACCEL_XOUT_H;
  204. p_ext_t->user_data1=14;//_count;
  205. p_ext_t->_p_post_cb_func = cb_mpu6050_readbytes;
  206. p_ext_t->pbuf_count=1;//1 - это адрес регистра, кол-во байт чтения выставим в колбэке
  207. p_ext_t->pbuf_tx=(uint8_t*)&p_ext_t->user_data0;//TX!!!!!!!
  208. p_ext_t->pbuf_rx=(uint8_t*)&gdata14;//RX!!!
  209. p_ext_t->p_pre_SetTXRXBuf=EXT_SetTXRXBuf_i2c;
  210. p_ext_t->reference_count=1;
  211. ad0x0_i2c2_push(ADQ_HAL_ADDR_TX_BUF_SEQ_FIRST_EXT,h_ext);
  212. ad0x0_i2c2_push(ADQ_HAL_ADDR_RX_BUF_SEQ_LAST_EXT,h_ext);
  213. /* ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_W);
  214. ad0x0_i2c2_push(ADQ_TX,_reg);
  215. ad0x0_i2c2_push(ADQ_START_ADDR,MPU6050_ADDRESS_R);
  216. ad0x0_i2c2_push_rx_pbuf_stop_ext(NULL,_pbuf,_count);*/
  217. }
  218. /*#define AD0X0_6050_LE_SWAP(X,Y) X = ((uint16_t)Y >> 8)|((uint16_t)Y << 8);
  219. static void mpu6050_damn_lendian(void){
  220. //gdata.ax=(gdata.ax >> 8)|(gdata.ax << 8);
  221. memcpy(&gdata_le,&gdata,sizeof(ad0x0_gyrodata_s));
  222. //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s));
  223. AD0X0_6050_LE_SWAP(gdata_be.ax,gdata_le.ax);
  224. AD0X0_6050_LE_SWAP(gdata_be.ay,gdata_le.ay);
  225. AD0X0_6050_LE_SWAP(gdata_be.az,gdata_le.az);
  226. AD0X0_6050_LE_SWAP(gdata_be.gx,gdata_le.gx);
  227. AD0X0_6050_LE_SWAP(gdata_be.gy,gdata_le.gy);
  228. AD0X0_6050_LE_SWAP(gdata_be.gz,gdata_le.gz);
  229. //memcpy(&gdata_be,&gdata,sizeof(ad0x0_gyrodata_s));
  230. }*/
  231. void cb_mpu5060_upd_data(uint8_t _sf_id,ad0x0_i2c_desc_s *pdi2c,void *p_i2c_ext_t){
  232. //mpu6050_damn_lendian(); перенес в mpu6050_read14.cb_mpu6050_readbytes2
  233. extern void ad0x0_gyro_datareaded_cb(void);
  234. ad0x0_gyro_datareaded_cb();
  235. }
  236. void update_gdata(void){
  237. if(ad0x0_i2c2_is_queue_ready()){
  238. mpu6050_read14();
  239. ad0x0_i2c2_push_ext_setfunc(0,cb_mpu5060_upd_data);
  240. last_update_tick=HAL_GetTick();
  241. }else{
  242. /*ошибка периода следования: это когда мы считываем текущие значения,
  243. и приходит очередное прерывание*/
  244. __ASM("nop");
  245. }
  246. }
  247. uint32_t mpu6050_get_last_update_tick(void){
  248. return last_update_tick;
  249. }
  250. uint8_t mpu6050_zavis(void){
  251. zavis=get_per_ms(last_update_tick)>300;
  252. return zavis;
  253. }
  254. #define AD_GYRO_EVMAX 2;
  255. //int g_gyro_evmax=10;
  256. void mpu6050_pin_irq(void){
  257. if(g_gyro_tick){
  258. update_gdata();
  259. }
  260. }