#include #include "spi.h" #include "cs1180.h" #include "clock.h" #include "libs/shark_types.h" #include "libs/logger.h" #define CS1180_RDATA 0X01 #define CS1180_RDATAC 0X03 #define CS1180_STOPC 0x0f #define CS1180_RREG 0x10 #define CS1180_WREG 0x50 #define CS1180_CALSELF 0xf0 #define CS1180_OCALSELF 0xf1 #define CS1180_SLFGCAL 0xf2 #define CS1180_OCALSYS 0xf3 #define CS1180_GCALSYS 0xf4 #define CS1180_WAKEUP 0xfb #define CS1180_SYNC 0xfc #define CS1180_SLEEP 0xfd #define CS1180_RESET 0xfe static float _cs1180_gain = 1.0f; static int CS1180_NOW_GAIN = CS1180_GAIN_128X; static uint8_t _cali_gain_regs[16 * 8]; static int cs1180_send_cmd(uint8_t data); static uint8_t cs1180_read_data(uint8_t data); static void cs1180_reset(void); void cs_delay(void) { uint32_t count = 1; while(count--); } static int _cs1180_ready = 0; int cs1180_is_ready(void){ return _cs1180_ready; } static void spi_write_reg(uint8_t reg, uint8_t *data, uint8_t len){ cs1180_send_cmd(CS1180_WREG|reg); cs1180_send_cmd(len - 1); while(len -- > 0){ cs1180_send_cmd(*data); data++; } } static void spi_read_reg(uint8_t reg, uint8_t *data, uint8_t len){ cs1180_send_cmd(CS1180_RREG|reg); cs1180_send_cmd(len - 1); delay_us(60); while(len -- > 0){ *data = cs1180_read_data(0xFF); data++; } } static uint8_t cs1180_dumy_read(int gain){ uint8_t *data = _cali_gain_regs + 16 * gain; while (IS_CS1180_NOT_READY()); cs1180_cs(0); cs_delay(); spi_read_reg(0x0, data, 16); cs_delay(); cs1180_cs(1); return data[0]; } /* 对芯片的偏移误差和增益误差进行纠正 */ static void cs1180_self_calibrate(void) { cs1180_cs(0); cs_delay(); cs1180_send_cmd(CS1180_CALSELF); cs_delay(); cs1180_cs(1); delay_us(50); /* wait calibrate finished */ while (IS_CS1180_NOT_READY()); while (!IS_CS1180_NOT_READY()); delay_us(50 * 1000); while (IS_CS1180_NOT_READY()); //drop first data } /* 对芯片的偏移误差进行纠正 */ __attribute__((unused)) static void cs1180_self_offset_calibrate(void) { cs1180_cs(0); cs1180_send_cmd(CS1180_OCALSELF); cs1180_cs(1); delay_us(50); /* wait calibrate finished */ while (IS_CS1180_NOT_READY()); while (!IS_CS1180_NOT_READY()); } /* 对芯片的增益误差进行纠正 */ __attribute__((unused)) static void cs1180_self_gain_calibrate(void) { cs1180_cs(0); cs1180_send_cmd(CS1180_SLFGCAL); cs1180_cs(1); delay_us(50); /* wait calibrate finished */ while (IS_CS1180_NOT_READY()); while (!IS_CS1180_NOT_READY()); } /* 对系统的失调误差(偏移误差)进行纠正, 必须要求输入为差分电压为0, */ void cs1180_sys_offset_calibrate(void) { cs1180_cs(0); cs_delay(); cs1180_send_cmd(CS1180_OCALSYS); delay_us(50); cs1180_cs(1); delay_us(50); /* wait calibrate finished */ while (IS_CS1180_NOT_READY()); while (!IS_CS1180_NOT_READY()); delay_us(10 * 1000); while (IS_CS1180_NOT_READY()); //drop first data } /* 对系统的增益误差进行纠正,必须输入正满幅度的电压, SP700,SP600未提供满辐电压,故这一项不做 */ __attribute__((unused)) static void cs1180_sys_gain_calibrate(void) { cs1180_cs(0); cs1180_send_cmd(CS1180_GCALSYS); cs1180_cs(1); delay_us(50); /* wait calibrate finished */ while (IS_CS1180_NOT_READY()); while (!IS_CS1180_NOT_READY()); } static void _cs1180_adc_set_gain(int gain){ /* 输出频率 15hz,参考电压1.235V 输出数据高位在前, * 输入缓冲器关闭,采样频率 OSC/128,数据格式双极性 */ uint8_t data[] = {0x00, 0x01, 0x00}; data[0] = 0xF & gain; cs1180_cs(0); cs_delay(); spi_write_reg(0x00, data, 3); cs_delay(); cs1180_cs(1); _cs1180_gain = 1 << gain; cs1180_self_calibrate(); cs1180_dumy_read(gain); } int cs1180_adc_set_gain_cali(int gain){ int count = 0; do { cs1180_reset(); delay_us(10); _cs1180_adc_set_gain(gain); delay_us(10); if (cs1180_dumy_read(gain) == gain){ break; } count ++; }while(count <= 20); if (count >= 20) { if (cs1180_dumy_read(gain) != gain){ return -1; } } delay_us(10*1000); cs1180_sys_offset_calibrate(); cs1180_dumy_read(gain); return 0; } static void cs1180_reset(void){ cs1180_cs(0); cs_delay(); cs1180_send_cmd(CS1180_RESET); cs_delay(); cs1180_cs(1); } void cs1180_adc_init(void){ _cs1180_ready = 0; CS1180_PWR_ENABLE(0); delay_us(100 * 1000); CS1180_PWR_ENABLE(1); delay_us(200 * 1000); spi1_init(); delay_us(10); #if 0 cs1180_adc_set_gain_cali(CS1180_GAIN_1X); cs1180_adc_set_gain_cali(CS1180_GAIN_8X); cs1180_adc_set_gain_cali(CS1180_GAIN_32X); #endif cs1180_adc_set_gain_cali(CS1180_GAIN_128X); _cs1180_ready = _cali_gain_regs[16 * CS1180_NOW_GAIN] == CS1180_NOW_GAIN; } int _cs1180_check_gain(int gain){ uint8_t data[13] = {0}; cs1180_cs(0); cs_delay(); spi_read_reg(0x0, data, 13); cs1180_cs(1); for (int i = 0; i < 13; i++){ if (data[i] != _cali_gain_regs[16 * gain + i]){ return 0; } } return 1; } int cs1180_adc_set_gain_online(int gain){ int count = 0; if (_cali_gain_regs[16 * CS1180_NOW_GAIN] == gain){ return 0; } sys_debug("change gain to %d\n", gain); do { cs1180_reset(); delay_us(10); cs1180_cs(0); cs_delay(); spi_write_reg(0x0, _cali_gain_regs + 16 * gain, 16); cs1180_cs(1); delay_us(10); if (_cs1180_check_gain(gain)){ break; } count ++; }while(count <= 5); if (count >= 5) { if (_cs1180_check_gain(gain) != 1){ sys_error("change gain error!!!\n"); return -1; } } CS1180_NOW_GAIN = gain; _cs1180_gain = 1 << gain; sys_debug("change gain success!\n"); return 0; } int cs1180_change_gain(int current){ if (abs(current) < 4000){ //4.5 return cs1180_adc_set_gain_online(CS1180_GAIN_128X); }/*else if (abs(current) < 12 * 1000){ //18 return cs1180_adc_set_gain_online(CS1180_GAIN_32X); }else if (abs(current) < 48 * 1000){ //72 return cs1180_adc_set_gain_online(CS1180_GAIN_8X); }else if (abs(current) < 160 * 1000){ return cs1180_adc_set_gain_online(CS1180_GAIN_1X); }*/ return -1; } void cs1180_adc_shutdown(void){ CS1180_PWR_ENABLE(0); spi1_deinit(); _cs1180_ready = 0; } static int cs1180_may_error = 0; void cs1180_log(void){ sys_error("cs1180 error %d\n", cs1180_may_error); } float cs1180_adc_sample(int *valide) { static int cs1180_low_ff_count = 0; uint8_t data[3] = {0,0,0}; int a = 0; while (IS_CS1180_NOT_READY()); //当drdy 为高时,不读取数据 #if 0 int retry = 5; while(retry-- >= 0) { cs1180_cs(0); cs1180_send_cmd(CS1180_RDATA); delay_us(60); data[0] = cs1180_read_data(0xFF); data[1] = cs1180_read_data(0xFF); data[2] = cs1180_read_data(0xFF); cs1180_cs(1); a = (data[0] << 16) | (data[1] << 8) | data[2]; a >>= 4; if (a != 0xFFFFF){//spi 上拉,所以如果读到的数据全F,说明可能cs1180没有数据输出,通过判断ready来确定是否要重读 break; } delay_us(100); if (IS_CS1180_NOT_READY()){ break; } sys_warning("cs1180 read adc retry!!!!\n"); } if ((a == 0xFFFFF) && !IS_CS1180_NOT_READY() && (valide != NULL)){ sys_error("cs1180 adc is not valide\n"); *valide = 0; } #endif cs1180_cs(0); cs1180_send_cmd(CS1180_RDATA); delay_us(60); data[0] = cs1180_read_data(0xFF); data[1] = cs1180_read_data(0xFF); data[2] = cs1180_read_data(0xFF); cs1180_cs(1); a = (data[0] << 16) | (data[1] << 8) | data[2]; a >>= 4; if (data[2] == 0xFF) { if (cs1180_low_ff_count ++ >= 10) { cs1180_may_error ++; } }else { cs1180_low_ff_count = 0; } if (a & 0x80000) { a = ~a; a = - (a&0x7FFFF); }else { a = a&0x7FFFF; } return (int)(((float)a / _cs1180_gain) * 0.9f); } static int cs1180_send_cmd(uint8_t cmd){ return spi1_send_byte(cmd, NULL); } static uint8_t cs1180_read_data(uint8_t data){ uint8_t r_data = 0xFF; spi1_send_byte(data, &r_data); return r_data; }