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; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。