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_SIZE512#define MAX_LINE_LEN((CMD_MAX_DATA_SIZE + 4) * 3)#define CMD_RETRY_DELAY100 /* in ms */#define RETRY_LIMIT3typedef 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 asthe 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 = NULLx = 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:deleteRETAILMSG(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")));#endifret = do_exec_cmd(i2c_file, cmd);//if execute failed,retry three timeswhile (!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 dataif (!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 addressudwTemp=I2CSLAVEADDR;DeviceIoControl(hI2C, IOCTL_I2C_SET_SLAVE_ADDRESS, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);//set i2c work modeudwTemp=I2C_SUBADDRESS_MODE_8;DeviceIoControl(hI2C, IOCTL_I2C_SET_SUBADDRESS_MODE, &udwTemp, sizeof(udwTemp), NULL, 0, NULL, NULL);//set i2c transfer speedudwTemp=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;}

获致幸福的不二法门是珍视你所拥有的遗忘你所没有的。

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

相关文章:

你感兴趣的文章:

标签云: