drv_qmc6310_v2.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*Includes ----------------------------------------------*/
  2. #include "drv_iic_back.h"
  3. #include "nrf_delay.h"
  4. #include "drv_qmc6310_v2.h"
  5. #include "exception.h"
  6. #include "system.h"
  7. /*Private macro ------------------------------------------------*/
  8. /* vendor chip id*/
  9. #define QMC6310U_IIC_ADDR (0x1c<<1)
  10. #define QMC6310N_IIC_ADDR (0x3c<<1)
  11. #define QMC6310_CHIP_ID_REG 0x00
  12. /*data output register*/
  13. #define QMC6310_DATA_OUT_X_LSB_REG 0x01
  14. #define QMC6310_DATA_OUT_X_MSB_REG 0x02
  15. #define QMC6310_DATA_OUT_Y_LSB_REG 0x03
  16. #define QMC6310_DATA_OUT_Y_MSB_REG 0x04
  17. #define QMC6310_DATA_OUT_Z_LSB_REG 0x05
  18. #define QMC6310_DATA_OUT_Z_MSB_REG 0x06
  19. /*Status registers */
  20. #define QMC6310_STATUS_REG 0x09
  21. /* configuration registers */
  22. #define QMC6310_CTL_REG_ONE 0x0A /* Contrl register one */
  23. #define QMC6310_CTL_REG_TWO 0x0B /* Contrl register two */
  24. /* Magnetic Sensor Operating Mode MODE[1:0]*/
  25. #define QMC6310_SUSPEND_MODE 0x00
  26. #define QMC6310_NORMAL_MODE 0x01
  27. #define QMC6310_SINGLE_MODE 0x02
  28. #define QMC6310_H_PFM_MODE 0x03
  29. /*data output rate OSR2[2:0]*/
  30. #define OUTPUT_DATA_RATE_800HZ 0x00
  31. #define OUTPUT_DATA_RATE_400HZ 0x01
  32. #define OUTPUT_DATA_RATE_200HZ 0x02
  33. #define OUTPUT_DATA_RATE_100HZ 0x03
  34. /*oversample Ratio OSR[1]*/
  35. #define OVERSAMPLE_RATE_256 0x01
  36. #define OVERSAMPLE_RATE_128 0x00
  37. #define SET_RESET_ON 0x00
  38. #define SET_ONLY_ON 0x01
  39. #define SET_RESET_OFF 0x02
  40. #define QMC6310_DEFAULT_DELAY 200
  41. #define QMC6310_MAXHZ 0xC3
  42. #define QMC6310_200HZ 0x3D
  43. #define QMC6310_100HZ 0x39
  44. #define QMC6310_10HZ 0x31
  45. /*STRUCTION -----------------------------------------------------*/
  46. typedef struct drv_qmc6310
  47. {
  48. bool (*write)(uint8_t add,uint8_t reg,uint8_t* p,uint8_t len); //IIC - 写
  49. bool (*read)(uint8_t add,uint8_t reg,uint8_t* p,uint8_t len); //IIC - 读
  50. qmc_data_t cur_data; //当前QMC的数据
  51. drv_qmc_config_param_t cur_param; //当前QMC的配置
  52. } Drv_Qmc6310_t;
  53. /*Local Variable ----------------------------------------------*/
  54. static Drv_Qmc6310_t ob_qmc6310;
  55. static uint32_t iic_write_error_counter = 0; //iic写错误上报
  56. static uint32_t iic_read_error_counter = 0; //iic读错误上报
  57. /*Local Functions ----------------------------------------------*/
  58. static bool qmc6310_get_chipid(void)
  59. {
  60. bool ret;
  61. uint8_t chipid = 0xFF;
  62. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_CHIP_ID_REG,&chipid,1);
  63. if(ret == false)
  64. {
  65. return false;
  66. }
  67. // SEGGER_RTT_printf(0,"chipid:%d\r\n",chipid);
  68. if(chipid != 0x80)
  69. {
  70. return false;
  71. }
  72. return true;
  73. }
  74. static bool platform_read(uint8_t add,uint8_t reg,uint8_t* p,uint8_t len)
  75. {
  76. bool ierror;
  77. ierror = IIC_BACK_ReadBytes(add,reg,p,len);
  78. if(ierror != true)
  79. {
  80. iic_read_error_counter++;
  81. }
  82. return ierror;
  83. }
  84. static bool platform_write(uint8_t add,uint8_t reg,uint8_t* p,uint8_t len)
  85. {
  86. bool ierror;
  87. ierror = IIC_BACK_WriteBytes(add,reg,p,len);
  88. if(ierror != true)
  89. {
  90. iic_write_error_counter++;
  91. }
  92. return ierror;
  93. }
  94. static void drv_qmc_iic_error_report_process(void)
  95. {
  96. char buff[30]={0};
  97. if(iic_write_error_counter > 0)
  98. {
  99. sprintf(buff,"iic_write_err,%d\r\n",iic_write_error_counter);
  100. Except_TxError(EXCEPT_IIC_RW,(const char *)buff);
  101. }
  102. if(iic_read_error_counter > 0)
  103. {
  104. sprintf(buff,"iic_read_err,%d\r\n",iic_read_error_counter);
  105. Except_TxError(EXCEPT_IIC_RW,(const char *)buff);
  106. }
  107. iic_write_error_counter = 0;
  108. iic_read_error_counter = 0;
  109. }
  110. /*API ----------------------------------------------*/
  111. /**
  112. @brief 初始化QMC6310驱动
  113. @param 无
  114. @return 错误代码 - [out] -1失败,0成功
  115. */
  116. int drv_qmc6310_Init(void)
  117. {
  118. nrf_gpio_cfg(
  119. PIN_BACK_SENSE_POWER,
  120. NRF_GPIO_PIN_DIR_OUTPUT,
  121. NRF_GPIO_PIN_INPUT_DISCONNECT,
  122. NRF_GPIO_PIN_NOPULL,
  123. NRF_GPIO_PIN_H0H1,
  124. NRF_GPIO_PIN_NOSENSE);
  125. nrf_gpio_cfg_output(PIN_BACK_SCL);
  126. nrf_gpio_cfg_output(PIN_BACK_SDA);
  127. nrf_gpio_pin_write(PIN_BACK_SCL,0);
  128. nrf_gpio_pin_write(PIN_BACK_SDA,0);
  129. //供电
  130. nrf_gpio_pin_write(PIN_BACK_SENSE_POWER,0);
  131. nrf_delay_ms(5);
  132. nrf_gpio_pin_write(PIN_BACK_SENSE_POWER,1);
  133. nrf_delay_ms(5);
  134. //初始化IIC错误上报
  135. Process_Start(1000,"qmc_iic_error_report",drv_qmc_iic_error_report_process);
  136. //初始化IIC
  137. IIC_BACK_Init();
  138. //初始化结构体
  139. memset(&ob_qmc6310, 0, sizeof(ob_qmc6310));
  140. ob_qmc6310.read = platform_read;
  141. ob_qmc6310.write = platform_write;
  142. ob_qmc6310.cur_param.mag_fs = QMC_MAG_FS_30GS;
  143. ob_qmc6310.cur_param.mag_odr = QMC_MAG_ODR_OFF;
  144. if(qmc6310_get_chipid())
  145. {
  146. return 0;
  147. }
  148. return -1;
  149. }
  150. /**
  151. @brief QMC6310断电
  152. @param 无
  153. @return 错误代码 - [out] -1失败,0成功
  154. */
  155. int drv_qmc6310_power_off(void)
  156. {
  157. nrf_gpio_cfg(
  158. PIN_BACK_SENSE_POWER,
  159. NRF_GPIO_PIN_DIR_OUTPUT,
  160. NRF_GPIO_PIN_INPUT_DISCONNECT,
  161. NRF_GPIO_PIN_NOPULL,
  162. NRF_GPIO_PIN_H0H1,
  163. NRF_GPIO_PIN_NOSENSE);
  164. nrf_gpio_cfg_output(PIN_BACK_SCL);
  165. nrf_gpio_cfg_output(PIN_BACK_SDA);
  166. nrf_gpio_pin_write(PIN_BACK_SCL,0);
  167. nrf_gpio_pin_write(PIN_BACK_SDA,0);
  168. //供电
  169. nrf_gpio_pin_write(PIN_BACK_SENSE_POWER,0);
  170. return 0;
  171. }
  172. /**
  173. @brief QMC6310上电(默认配置挂起)
  174. @param 无
  175. @return 错误代码 - [out] -1失败,0成功
  176. */
  177. int drv_qmc6310_power_on(void)
  178. {
  179. nrf_gpio_pin_write(PIN_BACK_SENSE_POWER,1);
  180. //初始化IIC
  181. IIC_BACK_Init();
  182. memset(&ob_qmc6310.cur_data,0,sizeof(ob_qmc6310.cur_data));
  183. ob_qmc6310.cur_param.mag_fs = QMC_MAG_FS_30GS;
  184. ob_qmc6310.cur_param.mag_odr = QMC_MAG_ODR_OFF;
  185. return 0;
  186. }
  187. /**
  188. @brief 设置MAG量程
  189. @param mag_fs - [in] MAG量程
  190. @return 错误代码 - [out] -1失败,0成功
  191. */
  192. int drv_qmc6310_set_mag_fs(QMC_MAG_FS_e mag_fs)
  193. {
  194. bool ret;
  195. uint8_t data;
  196. if(ob_qmc6310.cur_param.mag_fs != mag_fs)
  197. {
  198. switch(mag_fs)
  199. {
  200. case QMC_MAG_FS_30GS:
  201. data = QMC_MAG_FS_30GS;
  202. ret = ob_qmc6310.write(QMC6310U_IIC_ADDR,QMC6310_CTL_REG_TWO,&data,1);
  203. if(ret == false)return -1;
  204. data = 0xFF;
  205. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_CTL_REG_TWO,&data,1);
  206. if(ret == false || data != QMC_MAG_FS_30GS)return -1;
  207. ob_qmc6310.cur_param.mag_fs = QMC_MAG_FS_30GS;
  208. break;
  209. }
  210. }
  211. return 0;
  212. }
  213. /**
  214. @brief 获取配置MAG采样频率需要的步骤数量
  215. @return 错误代码 - [out] 配置MAG采样频率需要的步骤数量
  216. */
  217. int drv_qmc6310_get_mag_odr_flow(void)
  218. {
  219. return 4;
  220. }
  221. /**
  222. @brief 设置MAG采样频率
  223. @param mag_odr - [in] MAG采样频率
  224. @param flow - [in] 当前需要处理的步骤
  225. @return 错误代码 - [out] -1失败,0成功
  226. */
  227. int drv_qmc6310_set_mag_odr(QMC_MAG_ODR_e mag_odr, int flow)
  228. {
  229. int ret = -1;
  230. bool err;
  231. uint8_t data;
  232. if(flow <= 0 || flow >= 5)return -1;
  233. if(ob_qmc6310.cur_param.mag_odr != mag_odr)
  234. {
  235. switch(flow)
  236. {
  237. case 1:
  238. //define the sign for x y and z axis
  239. if(mag_odr != QMC_MAG_ODR_OFF)
  240. {
  241. data = 0x06;
  242. err = ob_qmc6310.write(QMC6310U_IIC_ADDR,0x29,&data,1);
  243. if(err == false)return -1;
  244. else ret = 0;
  245. }
  246. else
  247. {
  248. ret = 0;
  249. }
  250. break;
  251. case 2:
  252. //define the sign for x y and z axis
  253. if(mag_odr != QMC_MAG_ODR_OFF)
  254. {
  255. data = 0xFF;
  256. err = ob_qmc6310.read(QMC6310U_IIC_ADDR,0x29,&data,1);
  257. if(err == false || data != 0x06)return -1;
  258. else ret = 0;
  259. }
  260. else
  261. {
  262. ret = 0;
  263. }
  264. break;
  265. case 3:
  266. //set odr
  267. data = mag_odr;
  268. err = ob_qmc6310.write(QMC6310U_IIC_ADDR,QMC6310_CTL_REG_ONE,&data,1);
  269. if(err == false)return -1;
  270. else ret = 0;
  271. break;
  272. case 4:
  273. data = 0xFF;
  274. err = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_CTL_REG_ONE,&data,1);
  275. if(err == false || data != mag_odr)return -1;
  276. else{
  277. ret = 0;
  278. ob_qmc6310.cur_param.mag_odr = mag_odr;
  279. }
  280. break;
  281. }
  282. }
  283. else
  284. {
  285. return 0;
  286. }
  287. return ret;
  288. }
  289. /**
  290. @brief 获取LSM配置参数
  291. @param param - [in] LSM配置参数
  292. @return 错误代码 - [out] -1失败,0成功
  293. */
  294. int drv_qmc6310_get_config_param(drv_qmc_config_param_t *p_param)
  295. {
  296. *p_param = ob_qmc6310.cur_param;
  297. return 0;
  298. }
  299. /**
  300. @brief 获取LSM的ACC数据
  301. @param p_data - [out] 返回的ACC三轴数据
  302. @return 错误代码 - [out] -1失败,0成功
  303. */
  304. int drv_qmc6310_get_mag_data(qmc_data_t *p_data)
  305. {
  306. bool ret;
  307. unsigned char mag_data[6];
  308. mag_data[0] = QMC6310_DATA_OUT_X_LSB_REG;
  309. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_DATA_OUT_X_LSB_REG,mag_data,6);
  310. if(ret == false)return -1;
  311. if(p_data != NULL)
  312. {
  313. p_data->mag[0] = (int16_t)(((mag_data[1]) << 8) | mag_data[0]);
  314. p_data->mag[1] = (int16_t)(((mag_data[3]) << 8) | mag_data[2]);
  315. p_data->mag[2] = (int16_t)(((mag_data[5]) << 8) | mag_data[4]);
  316. }
  317. return 0;
  318. }
  319. int drv_qmc6310_get_mag_id(void)
  320. {
  321. if(qmc6310_get_chipid())
  322. {
  323. return 0;
  324. }
  325. return -1;
  326. }
  327. int drv_qmc6310_selfcheck_mag(void)
  328. {
  329. int ret = 0;
  330. uint8_t data;
  331. unsigned char mag_data1[6];
  332. unsigned char mag_data2[6];
  333. int16_t mag_delta[3];
  334. // SEGGER_RTT_printf(0,"Write Register 29H by 0x06 (Define the sign for X Y and Z axis)\r\n");
  335. data = 0x06;
  336. ret = ob_qmc6310.write(QMC6310U_IIC_ADDR,0x29,&data,1);
  337. if(ret == -1)return -1;
  338. data = 0xFF;
  339. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,0x29,&data,1);
  340. if(ret == -1 || data != 0x06)return -2;
  341. // SEGGER_RTT_printf(0,"Write Register 0AH by 0x03 (set continuous mode)\r\n");
  342. data = 0x03;
  343. ret = ob_qmc6310.write(QMC6310U_IIC_ADDR,0x0A,&data,1);
  344. if(ret == -1)return -3;
  345. data = 0xFF;
  346. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,0x0A,&data,1);
  347. if(ret == -1 || data != 0x03)return -4;
  348. // SEGGER_RTT_printf(0,"Check status register 09H[0], 1 means ready\r\n");
  349. uint32_t timeout = 2000;
  350. do
  351. {
  352. data = 0xFF;
  353. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,0x09,&data,1);
  354. timeout--;
  355. }while((data & 0x01) != 0x01 && timeout != 0);
  356. if(ret == -1 || (data & 0x01) != 0x01)return -5;
  357. // SEGGER_RTT_printf(0,"Read data Register 01H ~ 06H, recording as datax1/datay1/dataz1\r\n");
  358. mag_data1[0] = QMC6310_DATA_OUT_X_LSB_REG;
  359. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_DATA_OUT_X_LSB_REG,mag_data1,6);
  360. if(ret == -1)return -6;
  361. // SEGGER_RTT_printf(0,"Write Register 0BH by 0x40(enter self-test function)\r\n");
  362. data = 0x40;
  363. ret = ob_qmc6310.write(QMC6310U_IIC_ADDR,0x0B,&data,1);
  364. if(ret == -1)return -7;
  365. data = 0xFF;
  366. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,0x0B,&data,1);
  367. if(ret == -1 || data != 0x40)return -8;
  368. // SEGGER_RTT_printf(0,"Waiting 5 millisecond until measurement ends\r\n");
  369. nrf_delay_ms(5);
  370. // SEGGER_RTT_printf(0,"Read data Register 01H ~ 06H, recording as datax2/datay2/dataz2\r\n");
  371. mag_data2[0] = QMC6310_DATA_OUT_X_LSB_REG;
  372. ret = ob_qmc6310.read(QMC6310U_IIC_ADDR,QMC6310_DATA_OUT_X_LSB_REG,mag_data2,6);
  373. if(ret == -1)return -9;
  374. // SEGGER_RTT_printf(0,"Calculate the delta (datax1-datax2), (datay1-datay2), (dataz1-dataz2)\r\n");
  375. mag_delta[0] = (int16_t)(((mag_data1[1]) << 8) | mag_data1[0]) - (int16_t)(((mag_data2[1]) << 8) | mag_data2[0]);
  376. mag_delta[1] = (int16_t)(((mag_data1[3]) << 8) | mag_data1[2]) - (int16_t)(((mag_data2[3]) << 8) | mag_data2[2]);
  377. mag_delta[2] = (int16_t)(((mag_data1[5]) << 8) | mag_data1[4]) - (int16_t)(((mag_data2[5]) << 8) | mag_data2[4]);
  378. // SEGGER_RTT_printf(0,"mag_delta:%d,%d,%d\r\n",mag_delta[0],mag_delta[1],mag_delta[2]);
  379. // extern void JS_RTT_Print(signed int Sine1,signed int Sine2,signed int Sine3);
  380. // JS_RTT_Print(mag_delta[0],mag_delta[1],mag_delta[2]);
  381. if((mag_delta[0] >= 600 && mag_delta[0] <= 1100) && (mag_delta[1] >= -1000 && mag_delta[1] <= -600) && (mag_delta[2] >= -500 && mag_delta[2] <= -100))
  382. return 0;
  383. else
  384. return -10;
  385. }