BQ27510 电量计的校准 的 C语言实现
根据TI官方MSP430平台移植修改过来的,在Omap37xx(wince)平台测试,理论上和平台无关,伸手党,赶紧复制粘贴代码吧。如果这篇文章帮助了你,给了好评也无妨。
- /*
- ================================================================================
- * Texas Instruments OMAP(TM) Platform Software
- * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved.
- *
- * Use of this software is controlled by the terms and conditions found
- * in the license agreement under which this software has been supplied.
- *
- ================================================================================
- */
- //
- // File: bqtool.c
- //
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <i2cproxy.h>
- #include "bq27500.h"
- #define CMD_MAX_DATA_SIZE 512
- #define MAX_LINE_LEN ((CMD_MAX_DATA_SIZE + 4) * 3)
- #define CMD_RETRY_DELAY 100 /* in ms */
- #define RETRY_LIMIT 3
- typedef enum {
- CMD_INVALID = 0,
- CMD_R, /* Read */
- CMD_W, /* Write */
- CMD_C, /* Compare */
- CMD_X, /* Delay */
- } cmd_type_t;
- /*
- * DO NOT change the order of fields - particularly reg
- * should be immediately followed by data
- */
- typedef struct {
- cmd_type_t cmd_type;
- unsigned char addr;
- unsigned char reg;
- union {
- unsigned char bytes[CMD_MAX_DATA_SIZE + 1];
- UINT delay;
- } data;
- unsigned char data_len;
- UINT32 line_num;
- CHAR *line;
- }cmd_t;
- static UINT32 line_num;
- /* Parse S into tokens separated by characters in DELIM.
- If S is NULL, the saved pointer in SAVE_PTR is used as
- the next starting point. For example:
- char s[] = "-abc-=-def";
- char *sp;
- x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
- x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
- x = strtok_r(NULL, "=", &sp); // x = NULL
- // s = "abc/0-def/0"
- */
- static char *strtok_r(char *s, const char *delim, char **save_ptr) {
- char *token;
- if (s == NULL) s = *save_ptr;
- /* Scan leading delimiters. */
- s += strspn(s, delim);
- if (*s == '\0')
- return NULL;
- /* Find the end of the token. */
- token = s;
- s = strpbrk(token, delim);
- if (s == NULL)
- /* This token finishes the string. */
- *save_ptr = strchr(token, '\0');
- else {
- /* Terminate the token and make *SAVE_PTR point past it. */
- *s = '\0';
- *save_ptr = s + 1;
- }
- return token;
- }
- static char *strtok(char *s, const char *delim)
- {
- static char *last;
- return strtok_r(s, delim, &last);
- }
- //写I2C,根据自己平台修改相关实现
- static BOOL i2c_write(HANDLE hI2C, cmd_t *cmd)
- {
- int ret;
- DWORD udwTemp;
- if(hI2C)
- {
- udwTemp=cmd->addr >>1;
- DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
- SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
- if(!WriteFile(hI2C, cmd->data.bytes, cmd->data_len, &udwTemp, NULL))
- {
- RETAILMSG(1,(TEXT("ERROR: i2c_write: I2c WriteFile failed.\r\n")));
- }
- }
- return TRUE;
- }
- //读I2C,根据自己平台修改相关实现
- static BOOL i2c_Read(HANDLE hI2C, cmd_t *cmd)
- {
- int ret;
- DWORD udwTemp;
- if(hI2C)
- {
- udwTemp=cmd->addr >>1;
- DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
- SetFilePointer(hI2C,LOWORD(cmd->reg),NULL,FILE_BEGIN);
- if(!ReadFile(hI2C, cmd->data.bytes, cmd->data_len,&udwTemp, NULL))
- {
- RETAILMSG(1,(TEXT("ERROR: i2c_Read: I2c ReadFile failed.\r\n")));
- return FALSE;
- }else
- {
- cmd->data_len=udwTemp;
- }
- }
- return TRUE;
- }
- static BOOL do_exec_cmd(HANDLE i2c_file, cmd_t *cmd)
- {
- unsigned char tmp_buf[CMD_MAX_DATA_SIZE];
- int j=0;
- switch (cmd->cmd_type) {
- case CMD_R:
- return i2c_Read(i2c_file, cmd);
- case CMD_W:
- return i2c_write(i2c_file, cmd);
- case CMD_C:
- memcpy(tmp_buf, cmd->data.bytes, cmd->data_len);
- if (!i2c_Read(i2c_file, cmd))
- return FALSE;
- if (memcmp(tmp_buf, cmd->data.bytes, cmd->data_len)) {
- RETAILMSG(1, (TEXT("Command C failed at line %d\r\n"),cmd->line_num));
- return FALSE;
- }
- return TRUE;
- case CMD_X:
- Sleep(cmd->data.delay);
- return TRUE;
- default:
- RETAILMSG(1, (TEXT("Unsupported command at line %d\r\n"),cmd->line_num));
- return FALSE;
- }
- }
- static BOOL execute_cmd(HANDLE i2c_file, cmd_t *cmd)
- {
- int i = 1,j=0;
- BOOL ret;
- 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));
- #if 0 //only for debug TODO:delete
- RETAILMSG(1,(TEXT("line=%d:"),cmd->line_num));
- for(j=0;j<cmd->data_len;j++)
- {
- RETAILMSG(1,(TEXT("%02x "),cmd->data.bytes[j]));
- }
- RETAILMSG(1,(TEXT("\r\n")));
- #endif
- ret = do_exec_cmd(i2c_file, cmd);
- //if execute failed,retry three times
- while (!ret && i < RETRY_LIMIT) {
- Sleep(CMD_RETRY_DELAY);
- ret = do_exec_cmd(i2c_file, cmd);
- i++;
- }
- if (!ret) {
- RETAILMSG(1, (TEXT("Command execution failed at line %d addr=0x%02x reg=0x%02x\r\n"),cmd->line_num, cmd->addr, cmd->reg));
- }
- return ret;
- }
- static BOOL get_delay(UINT *delay)
- {
- char *tok;
- UINT temp;
- tok = strtok(NULL, " ");
- if (!tok)
- return FALSE; /*end of line or file */
- if (1 != sscanf(tok, "%u", &temp)) {
- RETAILMSG(1, (TEXT("Syntax error while parsing delay at line %d\r\n"),line_num));
- return FALSE; /* syntax error */
- }
- *delay = (UINT)temp;
- return TRUE;
- }
- /*
- * Returns:
- * 0: success
- * 1: EOF
- * -1: Parse error
- */
- static int get_byte(unsigned char *byte)
- {
- char *tok;
- unsigned char temp;
- tok = strtok(NULL, " ");
- if (!tok)
- return 1; /*end of line or file */
- if ((strlen(tok) != 2) || (sscanf(tok, "%2x", &temp) != 1)) {
- RETAILMSG(1, (TEXT("Syntax error at line %d\r\n"), line_num));
- return -1; /* syntax error */
- }
- *byte = (unsigned char)temp;
- return 0; /* success */
- }
- static BOOL get_addr_n_reg(cmd_t *cmd)
- {
- if (get_byte(&cmd->addr))
- return FALSE;
- if (get_byte(&cmd->reg))
- return FALSE;
- return TRUE;
- }
- static BOOL get_data_bytes(cmd_t *cmd)
- {
- int ret, i = 0;
- cmd->data_len = 0;
- do {
- ret = get_byte(&cmd->data.bytes[i++]);
- } while ((ret == 0) && (i <= CMD_MAX_DATA_SIZE));
- if (ret == 0) {
- 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));
- return FALSE;
- }
- cmd->data_len = i - 1;
- return TRUE;
- }
- static BOOL get_line(FILE *bqfs_file, char **buffer)
- {
- int c;
- int i = 0;
- BOOL ret = TRUE;
- char *buf;
- buf = malloc(MAX_LINE_LEN);
- line_num++;
- while (1) {
- c = fgetc(bqfs_file);
- if (feof(bqfs_file)) {
- break;
- } else if (ferror(bqfs_file)) {
- RETAILMSG(1, (TEXT("File read error\r\n")));
- ret = FALSE;
- break;
- }
- if (((c == '\r') || (c == '\n') || (c == '\t')
- || (c == ' ')) && (i == 0)) {
- /*
- * Skip leading white space, if any, at the beginning
- * of the line because this interferes with strtok
- */
- RETAILMSG(1, (TEXT("Leading whitespace at line %d\r\n"),line_num));
- if (c == '\n')
- line_num++;
- continue; /* blank line, let's continue */
- } else if (c == '\n') {
- /* We've reached end of line */
- break;
- }
- buf[i++] = c;
- if (i == MAX_LINE_LEN) {
- /*
- * Re-allocate in case the line is longer than
- * expected
- */
- buf = realloc(buf, MAX_LINE_LEN * 2);
- RETAILMSG(1, (TEXT("Line %d longer than expected,reallocating..\r\n"), line_num));
- } else if (i == MAX_LINE_LEN * 2) {
- /*
- * The line is already twice the expected maximum length
- * - maybe the bqfs/dffs needs to be fixed
- */
- RETAILMSG(1, (TEXT("Line %d too long, abort parsing..\r\n"),line_num));
- ret = FALSE;
- break;
- }
- }
- *buffer = buf;
- buf[i] = '\0';
- if (i < 1)
- ret = FALSE;
- return ret;
- }
- static BOOL get_cmd(FILE *bqfs_file, cmd_t *cmd)
- {
- char *res;
- char *tok;
- char *buf = NULL;
- BOOL ret;
- while ((ret = get_line(bqfs_file, &buf))) {
- if (buf[0] == ';') {
- /*
- * Comment line - ignore it and get the
- * next line
- */
- RETAILMSG(0, (TEXT("Comment line,line_num=%d\r\n"),line_num));
- free(buf);
- } else {
- break;
- }
- }
- if (!ret)
- goto error;
- cmd->line_num = line_num;
- tok = strtok(buf, ":");
- if (!tok || (strlen(tok) != 1)) {
- RETAILMSG(1, (TEXT("Error parsing command at line %d\r\n"),line_num));
- goto error;
- }
- switch (tok[0]) {
- case 'R':
- case 'r':
- cmd->cmd_type = CMD_R;
- if (!get_addr_n_reg(cmd))
- goto error;
- break;
- case 'W':
- case 'w':
- cmd->cmd_type = CMD_W;
- if (!get_addr_n_reg(cmd))
- goto error;
- if (!get_data_bytes(cmd))
- goto error;
- break;
- case 'C':
- case 'c':
- cmd->cmd_type = CMD_C;
- if (!get_addr_n_reg(cmd))
- goto error;
- if (!get_data_bytes(cmd))
- goto error;
- break;
- case 'X':
- case 'x':
- cmd->cmd_type = CMD_X;
- cmd->data_len = 1; //only one data
- if (!get_delay(&cmd->data.delay))
- goto error;
- break;
- default:
- RETAILMSG(1, (TEXT("No command or unexpected command at line %d.\r\n"),line_num));
- goto error;
- }
- if(buf)
- {
- free(buf);
- }
- return TRUE;
- error:
- RETAILMSG(1, (TEXT("get_line error,line_num=%d\r\n"),line_num));
- cmd->cmd_type = CMD_INVALID;
- free(buf);
- return FALSE;
- }
- //Param:char *fname
- // File to flash BQ27510 generate by TI's engineer.
- // for example:bq27510G3.bqfs(with G2 update G3 firmware)
- int bqfs_flash(char *fname)
- {
- FILE *bqfs_file = NULL;
- cmd_t *cmd = NULL;
- int ret = 0;
- DWORD udwTemp;
- HANDLE hI2C=NULL;
- RETAILMSG(0,(TEXT("bqfs_flush beging...\r\n")));
- bqfs_file = fopen(fname, "r");
- if (!bqfs_file) {
- RETAILMSG(1,(TEXT("bqfs_flush fopen failed.\r\n")));
- ret = -1;
- goto end;
- }
- hI2C=CreateFile(BATT_I2C_PORT, GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, 0, NULL);
- if(!hI2C)
- {
- RETAILMSG(1,(TEXT("bqfs_flash: I2c CreateFile failed.\r\n")));
- ret = -1;
- goto end;
- }
- //I2C相关配置寻址,根据自己平台修改相关实现
- //set slave address
- udwTemp=I2CSLAVEADDR;
- DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
- //set i2c work mode
- udwTemp=I2C_SUBADDRESS_MODE_8;
- DeviceIoControl(hI2C, IOCTL_I2C_SET_SUBADDRESS_MODE, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
- //set i2c transfer speed
- udwTemp=SLOWSPEED_MODE;
- DeviceIoControl(hI2C, IOCTL_I2C_SET_BAUD_INDEX, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);
- cmd = malloc(sizeof(cmd_t));
- if(!cmd)
- {
- RETAILMSG(1, (TEXT("bqfs_flash malloc failed.\r\n")));
- ret=-1;
- goto end;
- }
- while (get_cmd(bqfs_file, cmd) && execute_cmd(hI2C, cmd));
- if (feof(bqfs_file)) {
- RETAILMSG(1, (TEXT("programmed successfully!\r\n")));
- ret = 0;
- } else {
- RETAILMSG(1, (TEXT("programming failed!!\r\n")));
- ret = -1;
- }
- end:
- if (cmd)
- free(cmd);
- if(hI2C)
- {
- CloseHandle(hI2C);
- hI2C=NULL;
- }
- if (bqfs_file)
- fclose(bqfs_file);
- return ret;
- }