BQ27510 电量计的校准 的 C语言实现

时间:2023-01-10 04:23:12

点击打开链接

根据TI官方MSP430平台移植修改过来的,在Omap37xx(wince)平台测试,理论上和平台无关,伸手党,赶紧复制粘贴代码吧。如果这篇文章帮助了你,给了好评也无妨。

  1. /*
  2. ================================================================================
  3. *             Texas Instruments OMAP(TM) Platform Software
  4. * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved.
  5. *
  6. * Use of this software is controlled by the terms and conditions found
  7. * in the license agreement under which this software has been supplied.
  8. *
  9. ================================================================================
  10. */
  11. //
  12. //  File:  bqtool.c
  13. //
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <i2cproxy.h>
  19. #include "bq27500.h"
  20. #define CMD_MAX_DATA_SIZE   512
  21. #define MAX_LINE_LEN        ((CMD_MAX_DATA_SIZE + 4) * 3)
  22. #define CMD_RETRY_DELAY     100 /* in ms */
  23. #define RETRY_LIMIT     3
  24. typedef enum {
  25. CMD_INVALID = 0,
  26. CMD_R,  /* Read */
  27. CMD_W,  /* Write */
  28. CMD_C,  /* Compare */
  29. CMD_X,  /* Delay */
  30. } cmd_type_t;
  31. /*
  32. * DO NOT change the order of fields - particularly reg
  33. * should be immediately followed by data
  34. */
  35. typedef struct {
  36. cmd_type_t cmd_type;
  37. unsigned char addr;
  38. unsigned char reg;
  39. union {
  40. unsigned char bytes[CMD_MAX_DATA_SIZE + 1];
  41. UINT delay;
  42. } data;
  43. unsigned char data_len;
  44. UINT32 line_num;
  45. CHAR    *line;
  46. }cmd_t;
  47. static UINT32 line_num;
  48. /* Parse S into tokens separated by characters in DELIM.
  49. If S is NULL, the saved pointer in SAVE_PTR is used as
  50. the next starting point.  For example:
  51. char s[] = "-abc-=-def";
  52. char *sp;
  53. x = strtok_r(s, "-", &sp);      // x = "abc", sp = "=-def"
  54. x = strtok_r(NULL, "-=", &sp);  // x = "def", sp = NULL
  55. x = strtok_r(NULL, "=", &sp);   // x = NULL
  56. // s = "abc/0-def/0"
  57. */
  58. static char *strtok_r(char *s, const char *delim, char **save_ptr) {
  59. char *token;
  60. if (s == NULL) s = *save_ptr;
  61. /* Scan leading delimiters.  */
  62. s += strspn(s, delim);
  63. if (*s == '\0')
  64. return NULL;
  65. /* Find the end of the token.  */
  66. token = s;
  67. s = strpbrk(token, delim);
  68. if (s == NULL)
  69. /* This token finishes the string.  */
  70. *save_ptr = strchr(token, '\0');
  71. else {
  72. /* Terminate the token and make *SAVE_PTR point past it.  */
  73. *s = '\0';
  74. *save_ptr = s + 1;
  75. }
  76. return token;
  77. }
  78. static char *strtok(char *s, const char *delim)
  79. {
  80. static char *last;
  81. return strtok_r(s, delim, &last);
  82. }
  83. //写I2C,根据自己平台修改相关实现
  84. static BOOL i2c_write(HANDLE hI2C, cmd_t *cmd)
  85. {
  86. int ret;
  87. DWORD udwTemp;
  88. if(hI2C)
  89. {
  90. udwTemp=cmd->addr >>1;
  91. DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
  92. SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
  93. if(!WriteFile(hI2C, cmd->data.bytes, cmd->data_len, &udwTemp, NULL))
  94. {
  95. RETAILMSG(1,(TEXT("ERROR: i2c_write: I2c WriteFile failed.\r\n")));
  96. }
  97. }
  98. return TRUE;
  99. }
  100. //读I2C,根据自己平台修改相关实现
  101. static BOOL i2c_Read(HANDLE hI2C, cmd_t *cmd)
  102. {
  103. int ret;
  104. DWORD udwTemp;
  105. if(hI2C)
  106. {
  107. udwTemp=cmd->addr >>1;
  108. DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
  109. SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
  110. if(!ReadFile(hI2C, cmd->data.bytes, cmd->data_len,&udwTemp, NULL))
  111. {
  112. RETAILMSG(1,(TEXT("ERROR: i2c_Read: I2c ReadFile failed.\r\n")));
  113. return FALSE;
  114. }else
  115. {
  116. cmd->data_len=udwTemp;
  117. }
  118. }
  119. return TRUE;
  120. }
  121. static BOOL do_exec_cmd(HANDLE i2c_file, cmd_t *cmd)
  122. {
  123. unsigned char tmp_buf[CMD_MAX_DATA_SIZE];
  124. int j=0;
  125. switch (cmd->cmd_type) {
  126. case CMD_R:
  127. return i2c_Read(i2c_file, cmd);
  128. case CMD_W:
  129. return i2c_write(i2c_file, cmd);
  130. case CMD_C:
  131. memcpy(tmp_buf, cmd->data.bytes, cmd->data_len);
  132. if (!i2c_Read(i2c_file, cmd))
  133. return FALSE;
  134. if (memcmp(tmp_buf, cmd->data.bytes, cmd->data_len)) {
  135. RETAILMSG(1, (TEXT("Command C failed at line %d\r\n"),cmd->line_num));
  136. return FALSE;
  137. }
  138. return TRUE;
  139. case CMD_X:
  140. Sleep(cmd->data.delay);
  141. return TRUE;
  142. default:
  143. RETAILMSG(1, (TEXT("Unsupported command at line %d\r\n"),cmd->line_num));
  144. return FALSE;
  145. }
  146. }
  147. static BOOL execute_cmd(HANDLE i2c_file, cmd_t *cmd)
  148. {
  149. int i = 1,j=0;
  150. BOOL ret;
  151. RETAILMSG(0,(TEXT("cmd:cmd_type=%d;addr=%02x,reg=%02x,cmd->data_len=%d,"),cmd->cmd_type,cmd->addr,cmd->reg,cmd->data_len));
  152. #if 0   //only for debug TODO:delete
  153. RETAILMSG(1,(TEXT("line=%d:"),cmd->line_num));
  154. for(j=0;j<cmd->data_len;j++)
  155. {
  156. RETAILMSG(1,(TEXT("%02x "),cmd->data.bytes[j]));
  157. }
  158. RETAILMSG(1,(TEXT("\r\n")));
  159. #endif
  160. ret = do_exec_cmd(i2c_file, cmd);
  161. //if execute failed,retry three times
  162. while (!ret && i < RETRY_LIMIT) {
  163. Sleep(CMD_RETRY_DELAY);
  164. ret = do_exec_cmd(i2c_file, cmd);
  165. i++;
  166. }
  167. if (!ret) {
  168. RETAILMSG(1, (TEXT("Command execution failed at line %d addr=0x%02x reg=0x%02x\r\n"),cmd->line_num, cmd->addr, cmd->reg));
  169. }
  170. return ret;
  171. }
  172. static BOOL get_delay(UINT *delay)
  173. {
  174. char *tok;
  175. UINT temp;
  176. tok = strtok(NULL, " ");
  177. if (!tok)
  178. return FALSE; /*end of line or file */
  179. if (1 != sscanf(tok, "%u", &temp)) {
  180. RETAILMSG(1, (TEXT("Syntax error while parsing delay at line %d\r\n"),line_num));
  181. return FALSE; /* syntax error */
  182. }
  183. *delay = (UINT)temp;
  184. return TRUE;
  185. }
  186. /*
  187. * Returns:
  188. *   0: success
  189. *   1: EOF
  190. *  -1: Parse error
  191. */
  192. static int get_byte(unsigned char *byte)
  193. {
  194. char *tok;
  195. unsigned char temp;
  196. tok = strtok(NULL, " ");
  197. if (!tok)
  198. return 1; /*end of line or file */
  199. if ((strlen(tok) != 2) || (sscanf(tok, "%2x", &temp) != 1)) {
  200. RETAILMSG(1, (TEXT("Syntax error at line %d\r\n"), line_num));
  201. return -1; /* syntax error */
  202. }
  203. *byte = (unsigned char)temp;
  204. return 0;   /* success */
  205. }
  206. static BOOL get_addr_n_reg(cmd_t *cmd)
  207. {
  208. if (get_byte(&cmd->addr))
  209. return FALSE;
  210. if (get_byte(&cmd->reg))
  211. return FALSE;
  212. return TRUE;
  213. }
  214. static BOOL get_data_bytes(cmd_t *cmd)
  215. {
  216. int ret, i = 0;
  217. cmd->data_len = 0;
  218. do {
  219. ret = get_byte(&cmd->data.bytes[i++]);
  220. } while ((ret == 0) && (i <= CMD_MAX_DATA_SIZE));
  221. if (ret == 0) {
  222. RETAILMSG(1, (TEXT("More than allowed number of data bytes at line %d, data_len %d, i %d\r\n"), cmd->line_num,cmd->data_len, i));
  223. return FALSE;
  224. }
  225. cmd->data_len = i - 1;
  226. return TRUE;
  227. }
  228. static BOOL get_line(FILE *bqfs_file, char **buffer)
  229. {
  230. int c;
  231. int i = 0;
  232. BOOL ret = TRUE;
  233. char *buf;
  234. buf = malloc(MAX_LINE_LEN);
  235. line_num++;
  236. while (1) {
  237. c = fgetc(bqfs_file);
  238. if (feof(bqfs_file)) {
  239. break;
  240. } else if (ferror(bqfs_file)) {
  241. RETAILMSG(1, (TEXT("File read error\r\n")));
  242. ret = FALSE;
  243. break;
  244. }
  245. if (((c == '\r') || (c == '\n') || (c == '\t')
  246. || (c == ' ')) && (i == 0)) {
  247. /*
  248. * Skip leading white space, if any, at the beginning
  249. * of the line because this interferes with strtok
  250. */
  251. RETAILMSG(1, (TEXT("Leading whitespace at line %d\r\n"),line_num));
  252. if (c == '\n')
  253. line_num++;
  254. continue;   /* blank line, let's continue */
  255. } else if (c == '\n') {
  256. /* We've reached end of line */
  257. break;
  258. }
  259. buf[i++] = c;
  260. if (i == MAX_LINE_LEN) {
  261. /*
  262. * Re-allocate in case the line is longer than
  263. * expected
  264. */
  265. buf = realloc(buf, MAX_LINE_LEN * 2);
  266. RETAILMSG(1, (TEXT("Line %d longer than expected,reallocating..\r\n"), line_num));
  267. } else if (i == MAX_LINE_LEN * 2) {
  268. /*
  269. * The line is already twice the expected maximum length
  270. * - maybe the bqfs/dffs needs to be fixed
  271. */
  272. RETAILMSG(1, (TEXT("Line %d too long, abort parsing..\r\n"),line_num));
  273. ret = FALSE;
  274. break;
  275. }
  276. }
  277. *buffer = buf;
  278. buf[i] = '\0';
  279. if (i < 1)
  280. ret = FALSE;
  281. return ret;
  282. }
  283. static BOOL get_cmd(FILE *bqfs_file, cmd_t *cmd)
  284. {
  285. char *res;
  286. char *tok;
  287. char *buf = NULL;
  288. BOOL ret;
  289. while ((ret = get_line(bqfs_file, &buf))) {
  290. if (buf[0] == ';') {
  291. /*
  292. * Comment line - ignore it and get the
  293. * next line
  294. */
  295. RETAILMSG(0, (TEXT("Comment line,line_num=%d\r\n"),line_num));
  296. free(buf);
  297. } else {
  298. break;
  299. }
  300. }
  301. if (!ret)
  302. goto error;
  303. cmd->line_num = line_num;
  304. tok = strtok(buf, ":");
  305. if (!tok || (strlen(tok) != 1)) {
  306. RETAILMSG(1, (TEXT("Error parsing command at line %d\r\n"),line_num));
  307. goto error;
  308. }
  309. switch (tok[0]) {
  310. case 'R':
  311. case 'r':
  312. cmd->cmd_type = CMD_R;
  313. if (!get_addr_n_reg(cmd))
  314. goto error;
  315. break;
  316. case 'W':
  317. case 'w':
  318. cmd->cmd_type = CMD_W;
  319. if (!get_addr_n_reg(cmd))
  320. goto error;
  321. if (!get_data_bytes(cmd))
  322. goto error;
  323. break;
  324. case 'C':
  325. case 'c':
  326. cmd->cmd_type = CMD_C;
  327. if (!get_addr_n_reg(cmd))
  328. goto error;
  329. if (!get_data_bytes(cmd))
  330. goto error;
  331. break;
  332. case 'X':
  333. case 'x':
  334. cmd->cmd_type = CMD_X;
  335. cmd->data_len = 1;       //only one data
  336. if (!get_delay(&cmd->data.delay))
  337. goto error;
  338. break;
  339. default:
  340. RETAILMSG(1, (TEXT("No command or unexpected command at line %d.\r\n"),line_num));
  341. goto error;
  342. }
  343. if(buf)
  344. {
  345. free(buf);
  346. }
  347. return TRUE;
  348. error:
  349. RETAILMSG(1, (TEXT("get_line error,line_num=%d\r\n"),line_num));
  350. cmd->cmd_type = CMD_INVALID;
  351. free(buf);
  352. return FALSE;
  353. }
  354. //Param:char *fname
  355. //  File to flash BQ27510 generate by TI's engineer.
  356. //  for example:bq27510G3.bqfs(with G2 update G3 firmware)
  357. int bqfs_flash(char *fname)
  358. {
  359. FILE *bqfs_file = NULL;
  360. cmd_t *cmd = NULL;
  361. int ret = 0;
  362. DWORD udwTemp;
  363. HANDLE hI2C=NULL;
  364. RETAILMSG(0,(TEXT("bqfs_flush beging...\r\n")));
  365. bqfs_file = fopen(fname, "r");
  366. if (!bqfs_file) {
  367. RETAILMSG(1,(TEXT("bqfs_flush fopen failed.\r\n")));
  368. ret = -1;
  369. goto end;
  370. }
  371. hI2C=CreateFile(BATT_I2C_PORT, GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, 0, NULL);
  372. if(!hI2C)
  373. {
  374. RETAILMSG(1,(TEXT("bqfs_flash: I2c CreateFile failed.\r\n")));
  375. ret = -1;
  376. goto end;
  377. }
  378. //I2C相关配置寻址,根据自己平台修改相关实现
  379. //set slave address
  380. udwTemp=I2CSLAVEADDR;
  381. DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
  382. //set i2c work mode
  383. udwTemp=I2C_SUBADDRESS_MODE_8;
  384. DeviceIoControl(hI2C, IOCTL_I2C_SET_SUBADDRESS_MODE, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
  385. //set i2c transfer speed
  386. udwTemp=SLOWSPEED_MODE;
  387. DeviceIoControl(hI2C, IOCTL_I2C_SET_BAUD_INDEX, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
  388. cmd = malloc(sizeof(cmd_t));
  389. if(!cmd)
  390. {
  391. RETAILMSG(1, (TEXT("bqfs_flash malloc failed.\r\n")));
  392. ret=-1;
  393. goto end;
  394. }
  395. while (get_cmd(bqfs_file, cmd) && execute_cmd(hI2C, cmd));
  396. if (feof(bqfs_file)) {
  397. RETAILMSG(1, (TEXT("programmed successfully!\r\n")));
  398. ret = 0;
  399. } else {
  400. RETAILMSG(1, (TEXT("programming failed!!\r\n")));
  401. ret = -1;
  402. }
  403. end:
  404. if (cmd)
  405. free(cmd);
  406. if(hI2C)
  407. {
  408. CloseHandle(hI2C);
  409. hI2C=NULL;
  410. }
  411. if (bqfs_file)
  412. fclose(bqfs_file);
  413. return ret;
  414. }