void nespad_poll_gamepad(nespad_t* gamepad) { uint8_t local_buff = 0x00; // Toggle Latch - which presents the first bit bit_set(*gamepad->port, BIT(gamepad->latch_pin)); _delay_us(PULSE_TIME); bit_clr(*gamepad->port, BIT(gamepad->latch_pin)); _delay_us(PULSE_TIME); // Read first bit local_buff = bit_get(PIND,BIT(gamepad->data_pin)); // Now get the next 7 bits with the clock for (int i = 0 ; i < 7 ; ++i) { bit_set(*gamepad->port, BIT(gamepad->clock_pin)); _delay_us(PULSE_TIME); bit_clr(*gamepad->port, BIT(gamepad->clock_pin)); _delay_us(PULSE_TIME); local_buff = (local_buff << 1) | bit_get(PIND,BIT(gamepad->data_pin)); } gamepad->buffer = local_buff; return; }
void set_wind_dir_none (void) { #ifdef DEBUG uart_puts ("nodir\r\n"); #endif bit_clr (PORTD, WIND_CLOCK ); bit_clr (PORTD, WIND_ANTICLOCK ); direction=NONE; }
void test_relais(void) { bit_clr(PORTD, P_BIT4); bit_clr(PORTD, P_BIT5); bit_clr(PORTD, P_BIT6); bit_clr(PORTD, P_BIT7); bit_set(PORTD, WIND_CLOCK); uart_puts ("0x80\r\n"); lcd_puts (0, "bit7 (wind-clock)\n"); delay(2000); bit_set(PORTD, MOTOR); uart_puts ("0x40\r\n"); lcd_puts (0, "bit5 (motor)\n"); delay(2000); bit_set(PORTD, FILL_WIND); uart_puts ("0x20\r\n"); lcd_puts (0, "bit6 (fill-wind)\n"); delay(2000); bit_set(PORTD, WIND_ANTICLOCK); uart_puts ("0x10\r\n"); lcd_puts (0, "bit4 (wind anticlock)\n"); delay(2000); lcd_clrscr(0); uart_puts ("mot\r\n"); lcd_puts (0, "motor\n"); start_motor(); delay(2000); stop_motor(); delay(500); uart_puts ("fill\r\n"); lcd_puts (0, "fill\n"); fill(); delay(2000); stop_motor(); uart_puts ("windleft\r\n"); lcd_puts (0, "windleft\n"); delay(500); set_wind_dir_left(); delay(5000); stop_motor(); }
void init_mcp3201(uint8_t chip, uint8_t cs, uint8_t clk, uint8_t data) { uint8_t bclk, bcs, bdout, bdin; bclk = 1<< (clk & P_BITMASK); b_clk[chip]=bclk; bdata= 1<< (data & P_BITMASK); b_data[chip]=bdout; bcs= 1<< (cs & P_BITMASK); b_cs[chip] = bcs; clk=clk & P_PORTMASK; if (clk==P_PORTA) {p_clk[chip]=&PORTA; DDRA|=bclk; } if (clk==P_PORTB) {p_clk[chip]=&PORTB; DDRB|=bclk;} if (clk==P_PORTC) {p_clk[chip]=&PORTC; DDRC|=bclk;} if (clk==P_PORTD) {p_clk[chip]=&PORTD; DDRD|=bclk;} data=data & P_PORTMASK; if (data==P_PORTA) {p_data[chip]=&PINA; DDRA&=~bdout; bit_set(PORTA, bdata);} if (data==P_PORTB) {p_data[chip]=&PINB; DDRB&=~bdout; bit_set(PORTB, bdata);} if (data==P_PORTC) {p_data[chip]=&PINC; DDRC&=~bdout; bit_set(PORTC, bdata);} if (data==P_PORTD) {p_data[chip]=&PIND; DDRD&=~bdout; bit_set(PORTD, bdata);} cs=cs & P_PORTMASK; if (cs==P_PORTA) {p_cs[chip]=&PORTA; DDRA|=bcs;} if (cs==P_PORTB) {p_cs[chip]=&PORTB; DDRB|=bcs;} if (cs==P_PORTC) {p_cs[chip]=&PORTC; DDRC|=bcs;} if (cs==P_PORTD) {p_cs[chip]=&PORTD; DDRD|=bcs;} bit_set(*p_cs[chip], b_cs[chip]); bit_clr(*p_clk[chip], b_clk[chip]); bit_set(*p_din[chip], b_din[chip]); }
void SWPwm::run() { SWPWM_T *ch; LIST_POS pos; while(1) { // wait timer interrupt m_timer.wait(); pos = m_lstCH.getHeadPos(); // get first channel while(pos) { ch = (SWPWM_T *)m_lstCH.getAt(pos); // get channel from list if ( ch ) { ch->flag++; // inc pwm count if ( ch->dutyCycle>0 ) { if ( bit_chk(ch->flag, CH_STATE) ) { if ( CH_COUNT>=ch->dutyCycle ) { // count to dutyCycle? ch->pin = LOW; // set output low bit_clr(ch->flag, CH_STATE); // change state } } else if ( CH_COUNT>=m_accuracy ) { // count to end ? ch->pin = HIGH; // set output high ch->flag = bit(CH_STATE); // change state & RESET count } } else { ch->pin = LOW; // always LOW when dutycycle=0 } } pos = m_lstCH.getNext(pos); // next channel } m_cycle++; } }
void set_wind_dir_left (void) { #ifdef DEBUG uart_puts ("left\r\n"); #endif bit_clr (PORTD, WIND_CLOCK ); bit_set (PORTD, WIND_ANTICLOCK ); direction=LEFT; }
void set_wind_dir_right (void) { #ifdef DEBUG uart_puts ("right\r\n"); #endif bit_set (PORTD, WIND_CLOCK ); bit_clr (PORTD, WIND_ANTICLOCK ); direction=RIGHT; }
extern int set_event(control_t* ctrl, int event, unsigned char enabled) { if(enabled) { bit_set(ctrl->events, event); } else { bit_clr(ctrl->events, event); } return 0; }
void hitachi_lcd_service(void){ if(NewCustomSymbolFlags){ set_flag(CGRAMUsed); static uint8_t DataByteNumber = 0, CustomSymbolNumber = 0; if(get_flag(CGRAMAddrSet)){ hitachi_lcd_write_data(*(CustomSymbol[CustomSymbolNumber] + DataByteNumber)); if(++DataByteNumber > 7){ bit_clr(NewCustomSymbolFlags, CustomSymbolNumber); clr_flag(CGRAMAddrSet); DataByteNumber = 0; CustomSymbolNumber = 0; } } else { while(!(NewCustomSymbolFlags & (1<<CustomSymbolNumber))) CustomSymbolNumber++; hitachi_lcd_set_address(CGRAM_ADDR(CustomSymbolNumber*8)); set_flag(CGRAMAddrSet); } } else { if(get_flag(CGRAMUsed)){ clr_flag(CGRAMUsed); clr_flag(DRAMAddrSet); CharNumber = 0; hitachi_lcd_set_address(DRAM_ADDR(0x00)); } else { switch(CharNumber){ case CHAR_IN_ROW: if(get_flag(DRAMAddrSet)){ clr_flag(DRAMAddrSet); hitachi_lcd_write_data(pLcdBuffer[CharNumber]); CharNumber++; } else { set_flag(DRAMAddrSet); hitachi_lcd_set_address(DRAM_ADDR(0x40)); } break; case CHAR_ON_LCD: if(get_flag(DRAMAddrSet)){ clr_flag(DRAMAddrSet); CharNumber = 0; hitachi_lcd_write_data(pLcdBuffer[CharNumber]); CharNumber++; } else { set_flag(DRAMAddrSet); hitachi_lcd_set_address(DRAM_ADDR(0x00)); } break; default: hitachi_lcd_write_data(pLcdBuffer[CharNumber]); CharNumber++; break; } } } }
bool CAdcKey::isPressed(ADKEY_T key, bool clearFlag) { bool res = bit_chk(m_flag, key); if (res && clearFlag) { m_mutex.lock(); bit_clr(m_flag, key); m_mutex.unlock(); } return res; }
void fill (void) { #ifdef DEBUG uart_puts ("fill\r\n"); #endif set_wind_dir_none (); bit_clr (PORTD, FILL_WIND ); turns_done=0; action=FILL; delay(100); start_motor(); }
void mcp4922_spiw (uint8_t chip, int16_t word, uint8_t dac) { volatile uint8_t *pcs, *pldac; uint8_t bcs, bldac; if ((word & CNTRL)==0) { word|=DEFAULT; if (dac==0) word|=DAC_A; } pcs=p_cs[chip]; pldac=p_ldac[chip]; bcs=b_cs[chip]; bldac=b_ldac[chip]; uart_printf ("pcs1:%x\n",pcs); // pcs=&PORTA; bit_clr(*pcs, bcs); // uart_printf ("pcs2:%d\n",pcs); SPDR= word>>8; while (!(SPSR & (1<<SPIF))); SPDR= word & 0xff; while (!(SPSR & (1<<SPIF))); // PORTA|=bcs; bit_set(*pcs, bcs); bit_clr(*pldac, bldac); udelay(2); bit_set(*pldac, bldac); }
unsigned int mcp3201_getw (uint8_t chip) { volatile uint8_t *pclk, *pcs, *pdata; uint8_t bclk, bcs, bdata; uint8_t v,i; unsigned int word; pclk=p_clk[chip]; pdata=p_data[chip]; pcs=p_cs[chip]; bclk=b_clk[chip]; bdata=b_data[chip]; bcs=b_cs[chip]; bit_clr(*pclk, bclk); bit_clr(*pcs, bcs); udelay (20); word=0; for (i=0; i<16; i++) { bit_set(*pclk, bclk); udelay(100); bit_clr(*pclk, bclk); udelay(100); word=word<<1; if (bit_get (*pdout, bdout)) word++; } udelay (100); bit_set(*pcs, bcs); return ((word>>1) & 0x0fff); }
void potentiometer() { int sinus [21] = {128,168,203,232,250,255,250,232,203,168,128,88,53,24,6,0,6,24,53,88,128}; while(1) { for(int i=0;i<20;i++) // send data to SPDR { bit_clr (PORTB,PB5); // set CS low SPDR = 0b00010001; // command byte while ((SPSR & 0x80) == 0) {} SPDR = sinus[i]; while ((SPSR & 0x80) == 0) {} bit_set(PORTB,PB5); // set CS high PINB = 0b00010000; _delay_ms(5); } } }
void init_mcp4922(uint8_t chip, uint8_t cs, uint8_t clk, uint8_t data, uint8_t ldac ) { uint8_t bclk, bcs, bdata, bldac; bclk=1<< (clk & P_BITMASK); b_clk [chip] = bclk; bdata=1<< (data & P_BITMASK); b_data[chip] = bdata; bcs=1<< (cs & P_BITMASK); b_cs [chip] = bcs; bldac=1<< (ldac & P_BITMASK); b_ldac[chip] = bldac; clk=clk & P_PORTMASK; if (clk==P_PORTA) {p_clk[chip]=&PORTA; DDRA|=bclk ;} if (clk==P_PORTB) {p_clk[chip]=&PORTB; DDRB|=bclk;} if (clk==P_PORTC) {p_clk[chip]=&PORTC; DDRC|=bclk;} if (clk==P_PORTD) {p_clk[chip]=&PORTD; DDRD|=bclk;} data=data & P_PORTMASK; if (data==P_PORTA) {p_data[chip]=&PORTA; DDRA|=bdata;} if (data==P_PORTB) {p_data[chip]=&PORTB; DDRB|=bdata;} if (data==P_PORTC) {p_data[chip]=&PORTC; DDRC|=bdata;} if (data==P_PORTD) {p_data[chip]=&PORTD; DDRD|=bdata;} cs=cs & P_PORTMASK; if (cs==P_PORTA) {p_cs[chip]=&PORTA; DDRA|=bcs;} if (cs==P_PORTB) {p_cs[chip]=&PORTB; DDRB|=bcs;} if (cs==P_PORTC) {p_cs[chip]=&PORTC; DDRC|=bcs;} if (cs==P_PORTD) {p_cs[chip]=&PORTD; DDRD|=bcs;} ldac=ldac & P_PORTMASK; if (ldac==P_PORTA) {p_ldac[chip]=&PORTA; DDRA|=bldac;} if (ldac==P_PORTB) {p_ldac[chip]=&PORTB; DDRB|=bldac;} if (ldac==P_PORTC) {p_ldac[chip]=&PORTC; DDRC|=bldac;} if (ldac==P_PORTD) {p_ldac[chip]=&PORTD; DDRD|=bldac;} bit_set(*p_cs[chip], b_cs[chip]); bit_clr(*p_clk[chip], b_clk[chip]); bit_set(*p_ldac[chip], b_ldac[chip]); }
void i2c_stop() { // STOP TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWSTO); // Wait for STOP // WARNING: A bad I2C line can cause this loop to hang //loop_until_bit_is_set(TWCR, TWSTO); byte counter = 255; // 255 * 5us = 1.275ms timeout while(bit_is_clear(TWCR, TWSTO) && counter--) delay_us(5); // Disable I2C bit_clr(TWCR, TWEN); power_twi_disable(); }
void setup() { // Init USI TWI Slave and enable interrupts usiTwiSlaveInit(NESPAD_SLAVE_ADDRESS, i2cReadFromRegister, i2cWriteToRegister); sei(); // clock / latch pair for gamepad 1 bit_set(DDRD, BIT(NES_CLOCK_1)); bit_set(DDRD, BIT(NES_LATCH_1)); // clock / latch pair for gamepad 2 bit_set(DDRB, BIT(NES_CLOCK_2)); bit_set(DDRB, BIT(NES_LATCH_2)); // shared data pin for all gamepads bit_clr(DDRD, BIT(NES_DATA)); }
int main( int argc, char **argv ) { unsigned long t = 0; printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 0 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 1 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 2 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 3 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 4 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 5 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 6 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 7 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 31 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 30 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 29 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 28 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_set( &t, 27 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); printf( "\n" ); bit_clr( &t, 0 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_clr( &t, 31 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_clr( &t, 1 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_clr( &t, 4 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); bit_clr( &t, 7 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); printf( "\n" ); bit_clr( &t, 16 ); printf( "0x%08lx has %d bits set\n", t, bit_cnt( &t ) ); return 0; }
bool i2c_read(byte* data, bool ack) { // Expects more data (ACK) or not (NACK) ack ? (bit_set(TWCR, TWEA)) : (bit_clr(TWCR, TWEA)); // Begin receiving bit_set(TWCR, TWINT); // Wait for finish loop_until_bit_is_set(TWCR, TWINT); // Check status byte status = TW_STATUS; if(status != TW_MR_DATA_ACK && status != TW_MR_DATA_NACK) return false; // Read data *data = TWDR; return true; }
// Reset to known state (as per what the DS3231 datasheet says) void i2c_resetState() { bit_clr(TWCR, TWEN); // Disable TWI pinMode(SDA, INPUT); pinPullup(SDA, PULLUP_ENABLE); delay(1); // Toggle SDL until SDA goes HIGH or times out byte count = 64; // 64 * 1ms = 64ms timeout while(!pinRead(SDA) && count--) { delay(1); pinWrite(SDL, TOGGLE); } // Back to normal pinMode(SDA, OUTPUT); pinMode(SDL, OUTPUT); pinWrite(SDA, HIGH); pinWrite(SDL, HIGH); }
uint8_t ADT_check() { uint8_t i; for(i=0;i<ADT_sensor_count;i++) { #ifdef debug uart_print("ADT chk: "); uart_num(i,1); #endif if(i2c_start(ADT_addr_base|i,I2C_READ)) { bit_set(ADT_status,BIT(i));//set Ith bit as sign of sensor error #ifdef debug uart_println(" FAIL"); #endif } else { i2c_read(0); bit_clr(ADT_status,BIT(i));//set as working #ifdef debug uart_println(" OK"); #endif } i2c_stop(); } if(ADT_minimum_working > ADT_get_working_count()) { error_flags.ADT=1; return 1; } else { error_flags.ADT=0; return 0; } }
void mcp4922_putw (uint8_t chip, int16_t word, uint8_t dac) { volatile uint8_t *pclk, *pcs, *pdata, *pldac; uint8_t bclk, bcs, bdata, bldac; uint8_t i; if ((word & CNTRL)==0) { word|=DEFAULT; if (dac==0) word|=DAC_A; } pclk=p_clk[chip]; pdata=p_data[chip]; pcs=p_cs[chip]; pldac=p_ldac[chip]; bclk=b_clk[chip]; bdata=b_data[chip]; bcs=b_cs[chip]; bldac=b_ldac[chip]; bit_clr(*pcs, bcs); bit_clr (*pdata, bdata); for (i=0; i<16; i++) { bit_clr(*pclk, bclk); if ((word & 0x8000)) { bit_set (*pdata, bdata); } else { bit_clr (*pdata, bdata); } bit_set(*pclk, bclk); word=word<<1; } bit_clr(*pclk, bclk); bit_set(*pcs, bcs); bit_clr(*pldac, bldac); udelay(2); bit_set(*pldac, bldac); }
void CButton::run() { CTimeout bounce; while(1) { if ( bit_chk(m_flag, KEY_FLAG_DOWN) ) { if ( m_pin==HIGH ){ if ( bounce.isExpired(10) ) { bit_clr(m_flag, KEY_FLAG_DOWN); onKeyUp(); // call virtual function "onKeyUp()" } } else { bounce.reset(); } } else { if ( m_pin==LOW ){ if ( bounce.isExpired(5) ) { bit_set(m_flag, KEY_FLAG_DOWN); onKeyDown(); // call virtual function "onKeyDown()" } } else { bounce.reset(); } } } }
void tab_parse(char *file, char *user) /* Parse a crontab file and add its data to the tables. Handle errors by * yourself. Table is owned by 'user' if non-null. */ { crontab_t **atab, *tab; cronjob_t **ajob, *job; int fd; struct stat st; char *p, *q; size_t n; ssize_t r; int ok, wc; for (atab= &crontabs; (tab= *atab) != nil; atab= &tab->next) { if (strcmp(file, tab->file) == 0) break; } /* Try to open the file. */ if ((fd= open(file, O_RDONLY)) < 0 || fstat(fd, &st) < 0) { if (errno != ENOENT) { log(LOG_ERR, "%s: %s\n", file, strerror(errno)); } if (fd != -1) close(fd); return; } /* Forget it if the file is awfully big. */ if (st.st_size > TAB_MAX) { log(LOG_ERR, "%s: %lu bytes is bigger than my %lu limit\n", file, (unsigned long) st.st_size, (unsigned long) TAB_MAX); return; } /* If the file is the same as before then don't bother. */ if (tab != nil && st.st_mtime == tab->mtime) { close(fd); tab->current= 1; return; } /* Create a new table structure. */ tab= allocate(sizeof(*tab)); tab->file= allocate((strlen(file) + 1) * sizeof(tab->file[0])); strcpy(tab->file, file); tab->user= nil; if (user != nil) { tab->user= allocate((strlen(user) + 1) * sizeof(tab->user[0])); strcpy(tab->user, user); } tab->data= allocate((st.st_size + 1) * sizeof(tab->data[0])); tab->jobs= nil; tab->mtime= st.st_mtime; tab->current= 0; tab->next= *atab; *atab= tab; /* Pull a new table in core. */ n= 0; while (n < st.st_size) { if ((r = read(fd, tab->data + n, st.st_size - n)) < 0) { log(LOG_CRIT, "%s: %s", file, strerror(errno)); close(fd); return; } if (r == 0) break; n+= r; } close(fd); tab->data[n]= 0; if (strlen(tab->data) < n) { log(LOG_ERR, "%s contains a null character\n", file); return; } /* Parse the file. */ ajob= &tab->jobs; p= tab->data; ok= 1; while (ok && *p != 0) { q= get_token(&p); if (*q == '#' || q == p) { /* Comment or empty. */ while (*p != 0 && *p++ != '\n') {} continue; } /* One new job coming up. */ *ajob= job= allocate(sizeof(*job)); *(ajob= &job->next)= nil; job->tab= tab; if (!range_parse(file, q, job->min, 0, 59, &wc)) { ok= 0; break; } q= get_token(&p); if (!range_parse(file, q, job->hour, 0, 23, &wc)) { ok= 0; break; } q= get_token(&p); if (!range_parse(file, q, job->mday, 1, 31, &wc)) { ok= 0; break; } job->do_mday= !wc; q= get_token(&p); if (!range_parse(file, q, job->mon, 1, 12, &wc)) { ok= 0; break; } job->do_mday |= !wc; q= get_token(&p); if (!range_parse(file, q, job->wday, 0, 7, &wc)) { ok= 0; break; } job->do_wday= !wc; /* 7 is Sunday, but 0 is a common mistake because it is in the * tm_wday range. We allow and even prefer it internally. */ if (bit_isset(job->wday, 7)) { bit_clr(job->wday, 7); bit_set(job->wday, 0); } /* The month range is 1-12, but tm_mon likes 0-11. */ job->mon[0] >>= 1; if (bit_isset(job->mon, 8)) bit_set(job->mon, 7); job->mon[1] >>= 1; /* Scan for options. */ job->user= nil; while (q= get_token(&p), *q == '-') { q++; if (q[0] == '-' && q+1 == p) { /* -- */ q= get_token(&p); break; } while (q < p) switch (*q++) { case 'u': if (q == p) q= get_token(&p); if (q == p) goto usage; memmove(q-1, q, p-q); /* gross... */ p[-1]= 0; job->user= q-1; q= p; break; default: usage: log(LOG_ERR, "%s: bad option -%c, good options are: -u username\n", file, q[-1]); ok= 0; goto endtab; } } /* A crontab owned by a user can only do things as that user. */ if (tab->user != nil) job->user= tab->user; /* Inspect the first character of the command. */ job->cmd= q; if (q == p || *q == '#') { /* Rest of the line is empty, i.e. the commands are on * the following lines indented by one tab. */ while (*p != 0 && *p++ != '\n') {} if (*p++ != '\t') { log(LOG_ERR, "%s: contains an empty command\n", file); ok= 0; goto endtab; } while (*p != 0) { if ((*q = *p++) == '\n') { if (*p != '\t') break; p++; } q++; } } else { /* The command is on this line. Alas we must now be * backwards compatible and change %'s to newlines. */ p= q; while (*p != 0) { if ((*q = *p++) == '\n') break; if (*q == '%') *q= '\n'; q++; } } *q= 0; job->rtime= now; job->late= 0; /* It is on time. */ job->atjob= 0; /* True cron job. */ job->pid= IDLE_PID; /* Not running yet. */ tab_reschedule(job); /* Compute next time to run. */ } endtab: if (ok) tab->current= 1; }
// 数据包超时心跳包, 定时器自动复位, 一个单位时间一次 void heart_beart_notify_proc(Hachiko_EVT evt, void* _private, const struct Hachiko_food *self) { static int food = 0; if (evt == HACHIKO_TIMEOUT ) { unsigned int i = 0; struct charge_job * thiz = (struct charge_job *)_private; struct can_pack_generator *gen, *me; food ++; if ( food == 1000 ) { // 1S 为更新周期 thiz->bms.frame_speed_tx = thiz->bms.tx_seed; thiz->bms.frame_speed_rx = thiz->bms.rx_seed; thiz->bms.tx_seed = 0; thiz->bms.rx_seed = 0; food = 0; } for ( i = 0; thiz && i < thiz->bms.can_pack_gen_nr; i++ ) { gen = & thiz->bms.generator[i]; if ( gen->stage == thiz->bms.charge_stage ) { if ( gen->heartbeat < gen->period ) { gen->heartbeat += 1; } else { gen->heartbeat = gen->period; } } else { gen->heartbeat = 0; } } /* * 为了能够侦探到接受数据包的超时事件,需要在这里进行一个计数操作 * 当can_silence 计数大于等于 can_tolerate_silence 时认为对应数据包接收超时,需要在BMS逻辑主线程 * 中做相应处理. * * BEM和CEM不在超时统计范围内 */ for ( i = 0; thiz && i < thiz->bms.can_pack_gen_nr; i++ ) { me = &thiz->bms.generator[i]; //if ( bit_read(thiz, JF_GUN_OK) && bit_read(thiz, JF_ASSIT_PWR_ON) ) { if ( me->stage == thiz->bms.charge_stage ) { me->can_silence ++; } else { me->can_silence = 0; } //} else continue; if ( me->can_tolerate_silence < me->can_silence ) { switch (thiz->bms.charge_stage) { case CHARGE_STAGE_HANDSHACKING: if (me->can_pgn != PGN_BRM) break; if ( !bit_read(thiz, JS_BMS_RX_BRM_TIMEOUT) && !bit_read(thiz, JF_CHG_TRM_CHARGE) && !bit_read(thiz, JF_BMS_TRM_CHARGE) ) { bit_set(thiz, JS_BMS_RX_BRM_TIMEOUT); bit_clr(thiz, JF_BMS_BRM_OK); log_printf(WRN, "BMS: 握手阶段BMS通信"RED("故障(%d, V(RX):%d, V(TX):%d)")", 重新握手", me->can_tolerate_silence, thiz->bms.frame_speed_rx, thiz->bms.frame_speed_tx); thiz->bms.charge_stage = CHARGE_STAGE_HANDSHACKING; // 设置BMS通讯超时标志 // bit_set(thiz, JS_BMS_COMM_ERR); } else { me->can_silence = 0; } break; case CHARGE_STAGE_CONFIGURE: if (me->can_pgn != PGN_BRO && me->can_pgn != PGN_BCP ) break; if ( me->can_pgn == PGN_BRO && !bit_read(thiz, JS_BMS_RX_BRO_TIMEOUT) ) { bit_set(thiz, JS_BMS_RX_BRO_TIMEOUT); bit_clr(thiz, JF_BMS_RX_BRO); } else { me->can_silence = 0; } if ( me->can_pgn == PGN_BCP && !bit_read(thiz, JS_BMS_RX_BCP_TIMEOUT) ) { bit_set(thiz, JS_BMS_RX_BCP_TIMEOUT); bit_clr(thiz, JF_BMS_RX_BCP); } else { me->can_silence = 0; } if ( bit_read(thiz, JS_BMS_RX_BRO_TIMEOUT ) && bit_read(thiz, JS_BMS_RX_BCP_TIMEOUT ) && !bit_read(thiz, JF_CHG_TRM_CHARGE) && !bit_read(thiz, JF_BMS_TRM_CHARGE) ) { log_printf(WRN, "BMS: 配置阶段BMS通信"RED("故障(%d, V(RX):%d, V(TX):%d)")", 重新握手", me->can_tolerate_silence, thiz->bms.frame_speed_rx, thiz->bms.frame_speed_tx); thiz->bms.charge_stage = CHARGE_STAGE_HANDSHACKING; } break; case CHARGE_STAGE_CHARGING: if ( me->can_pgn == PGN_BCL ) { if ( !bit_read(thiz, JS_BMS_RX_BCL_TIMEOUT) && !bit_read(thiz, JF_CHG_TRM_CHARGE) && !bit_read(thiz, JF_BMS_TRM_CHARGE) ) { bit_set(thiz, JS_BMS_RX_BCL_TIMEOUT); bit_clr(thiz, JF_BMS_RX_BCL); log_printf(WRN, "BMS: 充电阶段BMS通信"RED("故障(%d, V(RX):%d, V(TX):%d)")", 重新握手", me->can_tolerate_silence, thiz->bms.frame_speed_rx, thiz->bms.frame_speed_tx); thiz->bms.charge_stage = CHARGE_STAGE_HANDSHACKING; } else { me->can_silence = 0; } } else if ( me->can_pgn == PGN_BST && (bit_read(thiz, JF_CHG_TRM_CHARGE) || bit_read(thiz, JF_BMS_TRM_CHARGE)) ) { bit_set(thiz, JS_BMS_RX_BST_TIMEOUT); log_printf(INF, "BMS: 接收BMS.BST 超时"); thiz->bms.charge_stage = CHARGE_STAGE_DONE; } else { break; } break; case CHARGE_STAGE_DONE: if (me->can_pgn != PGN_BSD) break; if ( !bit_read(thiz, JS_BMS_RX_BSD_TIMEOUT) && ! bit_read(thiz, JF_BMS_RX_BSD) ) { bit_set(thiz, JS_BMS_RX_BSD_TIMEOUT); log_printf(WRN, "BMS: 充电完成阶段BMS通信"RED("故障(%d, V(RX):%d, V(TX):%d)"), me->can_tolerate_silence, thiz->bms.frame_speed_rx, thiz->bms.frame_speed_tx); } else { me->can_silence = 0; } break; default: break; } } } } }
void start_motor (void){ #ifdef DEBUG uart_puts ("start motor\r\n"); #endif bit_clr (PORTD, MOTOR ); }
// CAN数据包接受完成 int about_packet_reciev_done(struct charge_job *thiz, struct bms_event_struct *param) { struct can_pack_generator *gen = NULL; switch ( param->can_id & 0x00FF00 ) { case PGN_CRM :// 0x000100, break; case PGN_CTS :// 0x000700, break; case PGN_CML :// 0x000800, break; case PGN_CCS :// 0x001200, break; case PGN_CST :// 0x001A00, bit_set(thiz, F_PCK_TX_CST); log_printf(INF, "BMS: PGN_CST 已经发送."); //thiz->bms.charge_stage = CHARGE_STAGE_DONE; log_printf(INF, "BMS: CHARGER change stage to "RED("CHARGE_STAGE_DONE")); break; case PGN_CSD :// 0x001D00, bit_set(thiz, F_PCK_TX_CSD); log_printf(INF, "BMS: PGN_CSD 已经发送."); break; case PGN_CRO :// 0x000A00, break; case PGN_CEM :// 0x001F00 break; case PGN_BRM :// 0x000200, BMS 车辆辨识报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BRM); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } if ( bit_read(thiz, S_BMS_COMM_DOWN) ) { log_printf(INF, "BMS: BMS 通信"GRN("恢复")); } bit_clr(thiz, S_BMS_COMM_DOWN); //__dump_can_param(param); if ( param->buff_payload == 8 ) { memcpy(&thiz->bms.vehicle_info, param->buff.rx_buff, 8); } else if ( param->buff_payload == sizeof(struct pgn512_BRM) ) { memcpy(&thiz->bms.vehicle_info, param->buff.rx_buff, sizeof(struct pgn512_BRM)); } if ( thiz->bms.vehicle_info.spn2565_bms_version[0] == 0x00 && thiz->bms.vehicle_info.spn2565_bms_version[1] == 0x01 && thiz->bms.vehicle_info.spn2565_bms_version[2] == 0x00 ) { } else { log_printf(WRN, "BMS: BMS not recognized due to invalid BMS VERSION(SPN2565)." "%02X%02X%02X", thiz->bms.vehicle_info.spn2565_bms_version[0], thiz->bms.vehicle_info.spn2565_bms_version[1], thiz->bms.vehicle_info.spn2565_bms_version[2]); bit_clr(thiz, F_BMS_RECOGNIZED); break; } if ( thiz->bms.vehicle_info.spn2566_battery_type == 0 || (thiz->bms.vehicle_info.spn2566_battery_type > 0x08 && thiz->bms.vehicle_info.spn2566_battery_type < 0xFF) ) { log_printf(WRN, "BMS: BMS not recognized due to invalid BATTERY TYPE(SPN2566)"); bit_clr(thiz, F_BMS_RECOGNIZED); break; } if ( thiz->bms.vehicle_info.spn2567_capacity / 10.0f > 1000.0f ) { log_printf(WRN, "BMS: BMS not recognized due to invalid CAP INFO(SPN2567)"); bit_clr(thiz, F_BMS_RECOGNIZED); break; } if ( thiz->bms.vehicle_info.spn2568_volatage / 10.0f > 750.0f ) { log_printf(WRN, "BMS: BMS not recognized due to invalid VOLTAGE INFO(SPN2568)"); bit_clr(thiz, F_BMS_RECOGNIZED); break; } log_printf(DBG_LV2, "BMS: BMS recognized....CAP: %.1f A.H, VOL: %.1f V", thiz->bms.vehicle_info.spn2567_capacity/10.0f, thiz->bms.vehicle_info.spn2568_volatage/10.0); if ( ! bit_read(thiz, F_BMS_RECOGNIZED ) ) { // send recognized event from here. } bit_set(thiz, F_BMS_RECOGNIZED); break; case PGN_BCP :// 0x000600, BMS 配置报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BCP); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } if ( bit_read(thiz, S_BMS_COMM_DOWN) ) { log_printf(INF, "BMS: BMS 通信"GRN("恢复")); } bit_clr(thiz, S_BMS_COMM_DOWN); if ( param->buff_payload != 13 ) { log_printf(WRN, "BMS: BCP packet size crash, need 13 gave %d", param->buff_payload); break; } memcpy(&thiz->bms.bms_config_info, param->buff.rx_buff, sizeof(struct pgn1536_BCP)); if ( thiz->bms.bms_config_info.spn2816_max_charge_volatage_single_battery / 100.0f > 24.0f ) { log_printf(WRN, "BMS: max_charge_volatage_single_battery out of rang(0-24)" "gave %.2f V (SPN2816)", thiz->bms.bms_config_info.spn2816_max_charge_volatage_single_battery / 100.0f); break; } if ( thiz->bms.bms_config_info.spn2817_max_charge_current / 10.0f > 400.0f ) { log_printf(WRN, "BMS: max_charge_current out of rang(-400-0)" "gave %.1f V (SPN2816)", thiz->bms.bms_config_info.spn2817_max_charge_current / 10.0f); break; } if ( thiz->bms.bms_config_info.spn2818_total_energy / 10.0f > 1000.0f ) { log_printf(WRN, "BMS: total_energy out of rang(0-1000 KW.H)" "gave %.1f KW.H (SPN2818)", thiz->bms.bms_config_info.spn2818_total_energy / 10.0f); break; } if ( thiz->bms.bms_config_info.spn2819_max_charge_voltage / 10.0f > 750.0f ) { log_printf(WRN, "BMS: max_charge_voltage out of rang(0-750 V)" "gave %.1f V (SPN2819)", thiz->bms.bms_config_info.spn2819_max_charge_voltage / 10.0f); break; } log_printf(DBG_LV2, "BMS: BCP done, BSVH: %.2f V, MAXi: %.1f A, " "CAP: %.1f KW.H, MVC: %.1f V, MT: %d, SOC: %.1f %%, V: %.1f V", thiz->bms.bms_config_info.spn2816_max_charge_volatage_single_battery/100.0f, (thiz->bms.bms_config_info.spn2817_max_charge_current-4000)/-10.0f, thiz->bms.bms_config_info.spn2818_total_energy/10.0f, thiz->bms.bms_config_info.spn2819_max_charge_voltage/10.0f, thiz->bms.bms_config_info.spn2820_max_temprature-50, thiz->bms.bms_config_info.spn2821_soc/10.0f, thiz->bms.bms_config_info.spn2822_total_voltage/10.0f); break; case PGN_BRO :// 0x000900, BMS 充电准备就绪报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BRO); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } log_printf(INF, "BMS is %s for charge.", param->buff.rx_buff[0] == 0x00 ? "not ready" : param->buff.rx_buff[0] == 0xAA ? "ready" : "<unkown status>"); if ( param->buff.rx_buff[0] == 0x00 ) { bit_clr(thiz, F_BMS_READY); bit_clr(thiz, F_CHARGER_READY); } else if ( param->buff.rx_buff[0] == 0xAA ) { bit_set(thiz, F_BMS_READY); bit_set(thiz, F_CHARGER_READY); } else { log_printf(WRN, "BMS: wrong can package data."); } break; case PGN_BCL :// 0x001000, BMS 电池充电需求报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BCL); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } if ( bit_read(thiz, S_BMS_COMM_DOWN) ) { log_printf(INF, "BMS: BMS 通信"GRN("恢复")); } bit_clr(thiz, S_BMS_COMM_DOWN); memcpy(&thiz->bms.bms_charge_need_now, param->buff.rx_buff, sizeof(struct pgn4096_BCL)); if ( thiz->bms.bms_charge_need_now.spn3072_need_voltage/10.0f > 750 ) { log_printf(WRN, "BMS: spn3072 range 0-750V gave: %d V", thiz->bms.bms_charge_need_now.spn3072_need_voltage); } else { //thiz->need_V = 10; thiz->need_V = thiz->bms.bms_charge_need_now.spn3072_need_voltage/10.0f; } if ( (thiz->bms.bms_charge_need_now.spn3073_need_current - 4000 )/-10.0f < 0 ) { log_printf(WRN, "BMS: spn3073 range -400-0A gave: %d A", thiz->bms.bms_charge_need_now.spn3073_need_current); } else { thiz->need_I = 0; double fi = (thiz->bms.bms_charge_need_now.spn3073_need_current-4000)/10.0; fi = fi < 0 ? -fi : fi; fi = 400.0 - fi; thiz->need_I = fi; } log_printf(DBG_LV3, "BMS: SETV: %.1f, SETI: %.1f", thiz->need_V, thiz->need_I); double fi = (thiz->bms.bms_charge_need_now.spn3073_need_current-4000)/10.0; log_printf(INF, "BMS.BCL: need I: %04X, %d, %d, |(NI - 4000)/10|=%.1f A, GBT: %.1f A", thiz->bms.bms_charge_need_now.spn3073_need_current, thiz->bms.bms_charge_need_now.spn3073_need_current, (unsigned)thiz->bms.bms_charge_need_now.spn3073_need_current, fi < 0 ? -fi : fi, (thiz->bms.bms_charge_need_now.spn3073_need_current-4000)/-10.0 ); log_printf(INF, "BMS: PGN_BCL fetched, V-need: %.1f V, I-need: %.1f mode: %s", thiz->bms.bms_charge_need_now.spn3072_need_voltage/10.0, (thiz->bms.bms_charge_need_now.spn3073_need_current+400)/-10.0f, thiz->bms.bms_charge_need_now.spn3074_charge_mode == CHARGE_WITH_CONST_VOLTAGE ? "恒压充电" : thiz->bms.bms_charge_need_now.spn3074_charge_mode == CHARGE_WITH_CONST_CURRENT ? "恒流充电" : "无效模式"); break; case PGN_BCS :// 0x001100, BMS 电池充电总状态报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BCS); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } log_printf(DBG_LV2, "BMS: PGN_BCS fetched."); memcpy(&thiz->bms.bms_all_battery_status, param->buff.rx_buff, sizeof(struct pgn4352_BCS)); if (thiz->bms.bms_all_battery_status.spn3075_charge_voltage/10.0 > 750.0f) { log_printf(WRN, "BMS: spn3075 range 0-750 gave: %.1f V", thiz->bms.bms_all_battery_status.spn3075_charge_voltage/10.0); } if (thiz->bms.bms_all_battery_status.spn3076_charge_current/10.0 > 400.0f) { log_printf(WRN, "BMS: spn3076 range -400-0 gave: %.1f V", -(thiz->bms.bms_all_battery_status.spn3076_charge_current/10.0)); } if (thiz->bms.bms_all_battery_status.spn3077_max_v_g_number/100.0 > 24.0 ) { log_printf(WRN, "BMS: spn3077 range 0-24 gave: %.1f V", -(thiz->bms.bms_all_battery_status.spn3077_max_v_g_number/100.0)); } if (thiz->bms.bms_all_battery_status.spn3078_soc > 100 ) { log_printf(WRN, "BMS: spn3078 range 0%%-100%% gave: %d%%", -(thiz->bms.bms_all_battery_status.spn3078_soc)); } log_printf(DBG_LV3, "BMS.BCS: CV: %.1f V, CI: %.1f A, gVmax: %.1f, " "SOC: %d %%, RT: %d min", thiz->bms.bms_all_battery_status.spn3075_charge_voltage/10.0, (thiz->bms.bms_all_battery_status.spn3076_charge_current-4000)/-10.0, (thiz->bms.bms_all_battery_status.spn3077_max_v_g_number&0xFFF)/100.0, thiz->bms.bms_all_battery_status.spn3078_soc, thiz->bms.bms_all_battery_status.spn3079_need_time); break; case PGN_BSM :// 0x001300, 动力蓄电池状态信息报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BSM); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } log_printf(DBG_LV2, "BMS: PGN_BSM fetched."); memcpy(&thiz->bms.bms_battery_status, param->buff.rx_buff, sizeof(struct pgn4864_BSM)); if ( SINGLE_BATTERY_VOLTAGE_HIGH == (thiz->bms.bms_battery_status.remote_single&SINGLE_BATTERY_VOLTAGE_HIGH)){ } if (SINGLE_BATTERY_VOLTAGE_LOW == (thiz->bms.bms_battery_status.remote_single&SINGLE_BATTERY_VOLTAGE_LOW)){ } if (BATTERY_CHARGE_CURRENT_HIGH == (thiz->bms.bms_battery_status.remote_single&BATTERY_CHARGE_CURRENT_HIGH)){ } if (BATTERY_CHARGE_CURRENT_LOW == (thiz->bms.bms_battery_status.remote_single&BATTERY_CHARGE_CURRENT_LOW)){ } if (BATTERY_TEMPRATURE_HIGH == (thiz->bms.bms_battery_status.remote_single&BATTERY_TEMPRATURE_HIGH)){ } if (BATTERY_TEMPRATURE_LOW == (thiz->bms.bms_battery_status.remote_single&BATTERY_TEMPRATURE_LOW)) { } if (INSULATION_FAULT == (thiz->bms.bms_battery_status.remote_single&INSULATION_FAULT)){ } if (INSULATION_UNRELIABLE== (thiz->bms.bms_battery_status.remote_single&INSULATION_UNRELIABLE)){ } if (CONNECTOR_STATUS_FAULT== (thiz->bms.bms_battery_status.remote_single&CONNECTOR_STATUS_FAULT)){ } if (CONNECTOR_STATUS_UNRELIABLE== (thiz->bms.bms_battery_status.remote_single&CONNECTOR_STATUS_UNRELIABLE)){ } if (CHARGE_ALLOWED== (thiz->bms.bms_battery_status.remote_single&CHARGE_ALLOWED)){ } if (CHARGE_FORBIDEN== (thiz->bms.bms_battery_status.remote_single&CHARGE_FORBIDEN)){ } break; case PGN_BMV :// 0x001500, 单体动力蓄电池电压报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BMV); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } memcpy(&thiz->bms.bms_battery_V, param->buff.rx_buff, sizeof(struct pgn5376_BMV)); log_printf(DBG_LV2, "BMS: PGN_BMV fetched."); break; case PGN_BMT :// 0x001600, 单体动力蓄电池温度报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BMT); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } memcpy(&thiz->bms.bms_battery_T, param->buff.rx_buff, sizeof(struct pgn5632_BMT)); log_printf(DBG_LV2, "BMS: PGN_BMT fetched."); break; case PGN_BSP :// 0x001700, 动力蓄电池预留报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BSP); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } log_printf(DBG_LV2, "BMS: PGN_BSP fetched."); break; case PGN_BST :// 0x001900, BMS 中止充电报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BST); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } /* * 接收到中止充电报文,充电机发送CTS,并关闭高压输出 */ bit_set(thiz, F_PCK_BMS_TRM); memcpy(&thiz->bms.bms_bst, param->buff.rx_buff, sizeof(struct pgn6400_BST)); log_printf(INF, "BMS: PGN_BST fetched."); break; case PGN_BSD :// 0x001C00, BMS 统计数据报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BSD); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } if ( bit_read(thiz, S_BMS_COMM_DOWN) ) { log_printf(INF, "BMS: BMS 通信"GRN("恢复")); } thiz->bms.charge_stage = CHARGE_STAGE_DONE; bit_clr(thiz, S_BMS_COMM_DOWN); memcpy(&thiz->bms.bms_stop_bsd, param->buff.rx_buff, sizeof(struct pgn7168_BSD)); log_printf(INF, "BMS.BSD: SOC: %d %%, Vmin: %.2f V, Vmax: %.2f V," "Tmin: %d, Tmax: %d", thiz->bms.bms_stop_bsd.end_soc, thiz->bms.bms_stop_bsd.min_bat_V/100.0f, thiz->bms.bms_stop_bsd.max_bat_V/100.0f, thiz->bms.bms_stop_bsd.min_bat_T - 50, thiz->bms.bms_stop_bsd.max_bat_T - 50); log_printf(DBG_LV2, "BMS: PGN_BSD fetched."); break; case PGN_BEM :// 0x001E00, BMS 错误报文 gen = gen_search(thiz->bms.generator, thiz->bms.can_pack_gen_nr, PGN_BEM); if ( gen ) { gen->can_counter ++; gen->can_silence = 0; } if ( param->buff.rx_buff[0] & 0x01 ) { log_printf(WRN, "BMS: 接收PSN2560=0x00的报文超时"); } if ( param->buff.rx_buff[0] & 0x02 ) { log_printf(WRN, "BMS: 接收PSN2560=0x00的报文不可信"); } if ( param->buff.rx_buff[0] & 0x04 ) { log_printf(WRN, "BMS: 接收PSN2560=0xAA的报文超时"); } if ( param->buff.rx_buff[0] & 0x08 ) { log_printf(WRN, "BMS: 接收PSN2560=0xAA的报文不可信"); } if ( param->buff.rx_buff[1] & 0x01 ) { log_printf(WRN, "BMS: 接收CTS和CML的报文超时"); } if ( param->buff.rx_buff[1] & 0x02 ) { log_printf(WRN, "BMS: 接收CTS和CML的报文不可信"); } if ( param->buff.rx_buff[1] & 0x04 ) { log_printf(WRN, "BMS: 接收充电机完成充电准备的报文超时"); } if ( param->buff.rx_buff[1] & 0x08 ) { log_printf(WRN, "BMS: 接收充电机完成充电准备的报文不可信"); } if ( param->buff.rx_buff[2] & 0x01 ) { log_printf(WRN, "BMS: 接收充电机状态的报文超时"); } if ( param->buff.rx_buff[2] & 0x02 ) { log_printf(WRN, "BMS: 接收充电机状态的报文不可信"); } if ( param->buff.rx_buff[2] & 0x04 ) { log_printf(WRN, "BMS: 接收充电机中止充电的报文超时"); } if ( param->buff.rx_buff[2] & 0x08 ) { log_printf(WRN, "BMS: 接收充电机中止充电的报文不可信"); } if ( param->buff.rx_buff[3] & 0x01 ) { log_printf(WRN, "BMS: 接收充电机充电统计的报文超时"); } if ( param->buff.rx_buff[3] & 0x02 ) { log_printf(WRN, "BMS: 接收充电机充电统计的报文不可信"); } log_printf(DBG_LV2, "BMS: PGN_BEM fetched."); break; default: log_printf(WRN, "BMS: un-recognized PGN %08X", param->can_id); break; } return ERR_OK; }