; ****************************************************************** ; * Include routine for akkuload, calculation and display routines * ; * (C)2005 by Gerh.Schmidt, info@avr-asm-tutorial.net * ; ****************************************************************** ; ; ************** EEPROM Init, Read and Write ****************** ; ; Initialises the Eeprom storage of akkus ; EpInit: clr ZH ; Z is Eeprom read pointer clr ZL clr R0 ; R0 is counter EpInit1: sbic EECR,EEWE ; wait for write end rjmp EpInit1 ; wait because write bit is set inc R0 ; next akku ldi rmp,cEepMax+1 ; check if beyond last id cp R0,rmp ; compare with max number brcc EpInit4 out EEARL,ZL ; set EEPROM read adress out EEARH,ZH sbi EECR,EERE ; set read enable EpInit2: sbic EECR,EERE ; wait for read ok rjmp EpInit2 ; wait on in rmp,EEDR ; read akku number cp rmp,R0 ; compare with akku number brne EpInit4 ; not correct, skip further read adiw ZL,1 ; next byte out EEARL,ZL ; set EEPROM read adress out EEARH,ZH sbi EECR,EERE ; set read enable EpInit3: sbic EECR,EERE ; wait for read ok rjmp EpInit3 ; wait on in rmp,EEDR ; read id byte cpi rmp,0xA0 ; must be between A0 and A3 brcs EpInit4 ; smaller than A0, skip further read cpi rmp,0xA4 brcc EpInit4 ; greater than A3, skip further read adiw ZL,15 ; next EEPROM location rjmp EpInit1 EpInit4: dec R0 ; store number of akkus sts sEaNm,R0 ret ; ; Read the Eeprom content of akku Id in rmp to the buffer ; EpRead: dec rmp ; starts with id=1 mov ZL,rmp ; copy to Z clr ZH lsl ZL ; *2 rol ZH lsl ZL ; *4 rol ZH lsl ZL ; *8 rol ZH lsl ZL ; *16 rol ZH ldi XH,HIGH(sEepB) ; X is buffer adress counter ldi XL,LOW(sEepB) EpRead1: sbic EECR,EEWE ; wait for end of write, if necessary rjmp EpRead1 out EEARH,ZH ; output read adress out EEARL,ZL sbi EECR,EERE ; set read enable EpRead2: sbic EECR,EERE ; wait for end of read rjmp EpRead2 in rmp,EEDR ; read byte st X+,rmp ; store in buffer adiw ZL,1 ; next byte in EEPROM mov rmp,ZL ; test for end andi rmp,0x0F ; check last four bits clear brne EpRead1 ; read another byte ret ; ; Write the buffer content to the EEPROM ; EpWrite: ldi XH,HIGH(sEepB) ; X is buffer adress counter ldi XL,LOW(sEepB) ld rmp,X ; read id number dec rmp ; starts with id=1 mov ZL,rmp ; copy to Z clr ZH lsl ZL ; *2 rol ZH lsl ZL ; *4 rol ZH lsl ZL ; *8 rol ZH lsl ZL ; *16 rol ZH EpWrite1: sbic EECR,EEWE ; wait for end of write, if necessary rjmp EpWrite1 out EEARH,ZH ; output write adress out EEARL,ZL ld rmp,X+ ; read byte from buffer out EEDR,rmp ; write to data register cli ; stop interrupts sbi EECR,EEMWE ; set write mode enable sbi EECR,EEWE ; set write enable sei ; enable interrupts adiw ZL,1 ; next byte in EEPROM mov rmp,ZL ; test for end andi rmp,0x0F ; check last four bits clear brne EpWrite1 ; write another byte ret ; ; Check Akku Id and add current to stored akku in Eeprom ; R0 is channel, preserves R0 and R1! ; EpStore: rcall GetAkkuId ; read id of the current channel tst rmp ; id=0? breq EpStore4 ; yes, return lds ZL,sEANm ; read the number of id's in EEPROM sec ; set carry cpc rmp,ZL ; compare with (number of id's+1) brcc EpStore4 ; greater than number of id's rcall EpRead ; read the EEPROM id to buffer ldi ZH,HIGH(sAdcC) ; point to measured capacity ldi ZL,LOW(sAdcC) add ZL,R0 ; add channel number add ZL,R0 ld XL,Z+ ; read loaded capacity to X ld XH,Z lds ZL,sENRL ; read rest capacity from buffer to Z lds ZH,sENRM add ZL,XL ; add loaded capacity adc ZH,XH lds XL,sENCL ; read nominal capacity to X lds XH,sENCM clr rmp ; clear counter EpStore1: cp ZL,XL ; compare accumulated capacity in Z with nominal in X cpc ZH,XH brcs EpStore2 ; number of loads ready sub ZL,XL ; subtract nominal capacity sbc ZH,XH inc rmp rjmp EpStore1 EpStore2: ; number of loads is in rmp sts sENRL,ZL ; store rest capacity in buffer sts sENRM,ZH tst rmp ; a full load? breq EpStore3 lds ZL,sENLL ; read number of loads add ZL,rmp sts sENLL,ZL ; store number of loads brcc EpStore3 ; no carry lds ZL,sENLM ; inc MSB inc ZL sts sENLM,ZL EpStore3: ; buffer is ready, write rcall EpWrite ; write the buffer to EEPROM EpStore4: ret ; ; *** Convert measured voltages to decimal voltages and currents *** ; ; Convert ADC value of 32 cycles to binary voltage ; sd32e in R3:R2, result in R3:R2, uses R6:R5:R4 ; Reference voltage is 5V, U[mV] = s32 * 39 / 256 ; Adc2mV: mov R4,R2 ; copy s32 to R6:R5:R4 mov R5,R3 clr R6 lsl R4 ; * 2 rol R5 rol R6 lsl R4 ; * 4 rol R5 rol R6 lsl R4 ; * 8 rol R5 rol R6 mov R0,R4 ; copy to rmp:R1:R0 mov R1,R5 mov rmp,R6 lsl R4 ; * 16 rol R5 rol R6 lsl R4 ; * 32 rol R5 rol R6 add R4,R0 ; * 40 adc R5,R1 adc R6,rmp clr rmp sub R4,R2 ; * 39 sbc R5,R3 sbc R6,rmp mov R2,R5 ; / 256 mov R3,R6 ldi rmp,0x80 ; round add rmp,R4 clr rmp adc R2,rmp adc R3,rmp ret ; ; Negative to positive/positive to negative ; Negative: neg R2 ; Two's complement clr rmp sbc rmp,R3 mov R3,rmp ret ; ; Convert mV difference to mA ; mV in R3:R2, result in R3:R2 ; Adc voltage reference is 5V ; mA = 11.84 * (s32odd - s32even) / 256 ; mV2mA: ldi rmp,0x80 ; test negative and rmp,R3 mov R0,rmp ; remember sign flag breq mV2mA1 ; not negative ; convert negative to positive rcall negative mV2mA1: mov R4,R2 ; copy to R6:R5:R4 mov R5,R3 clr R6 lsl R4 ; * 2 rol R5 rol R6 add R4,R2 ; * 3 adc R5,R3 clr rmp adc R6,rmp lsl R4 ; * 6 rol R5 rol R6 lsl R4 ; * 12 rol R5 rol R6 lsr R3 ; R3:R2 / 2 ror R2 lsr R3 ; R3:R2 / 4 ror R2 lsr R3 ; R3:R2 / 8 ror R2 sub R4,R2 ; * 11.88 sbc R5,R3 sbc R6,rmp mV2mA3: mov R2,R5 ; move the result to R3:R2, dividing by 256 mov R3,R6 ldi rmp,0x80 ; round result add rmp,R4 clr rmp adc R2,rmp adc R3,rmp tst R0 ; check negative breq mV2mA4 rjmp negative mV2mA4: ret ; ; Convert mA to mAh ; Input: R6:R5:R4 has the current as 256*I ; output: R3:R2 has the mAh as 256*mAh ; mA2mAh: mov R1,R4 ; copy the current to R3:R2:R1 mov R2,R5 mov R3,R6 lsr R3 ; divide the current by 2 ror R2 ror R1 lsr R3 ; divide the current by 4 ror R2 ror R1 ; The current in mA, multiplied by 64, is now in R3:R2:R1 clr rmp add R1,R5 ; add the original current to yield 65 * I adc R2,R6 adc R3,rmp ; The current in mA, multiplied by 65, is now in R3:R2:R1 lsl R4 ; now multiply the original current by 8 rol R5 rol R6 lsl R4 ; * 4 rol R5 rol R6 lsl R4 ; * 8 rol R5 rol R6 clr rmp ; round this up rol R4 ; upmost bit into carry adc R5,rmp adc R6,rmp add R1,R5 ; now at 8*I to 65*I to get 73*I adc R2,R6 adc R3,rmp ; The result of 73*I/256 is now in R3:R2 ; This number is equal to the mAh, multiplied by 256, ; that were stored in the accu in the last 4 seconds ret ; ; ********* 32 Measurement of voltages are completed ******* ; ; ADC completed 32 measurements ; Adc32m: cbr rFlg,1< threshold voltage? sbc R5,R3 brcc ChckStates6 ; no, go on rcall ToLoad rjmp ChckStates6 ChckStates3: ; state is 2 or higher cpi rmp,2 ; is channel loading? brne ChckStates5 ldi ZH,HIGH(sCh1LW) ; point to max. work ldi ZL,LOW(sCh1LW) rcall ChAdrs ; calculate channel adress ld R2,Z+ ; max work to R3:R2 ld R3,Z ldi ZH,HIGH(sAdcC) ; Z to selected capacity ldi ZL,LOW(sAdcC) add ZL,R0 ; correct channel address add ZL,R0 ld R4,Z+ ; current work to R4:R3 ld R5,Z sub R4,R2 ; capacity reached? sbc R5,R3 brcs ChckStates4 ; no, go on loading ldi rmp,0x03 ; set maintain state rcall ChSet ldi rmp,100 ; set pwm small rcall PwmSet rcall EpStore ; add capacity to the stored akku rjmp ChckStates6 ChckStates4: ldi ZH,HIGH(sCh1LC) ; point Z to load current ldi ZL,LOW(sCh1LC) rcall ChCurrent ; correct current to that value rjmp ChckStates6 ChckStates5: ; channel is maintained ldi ZH,HIGH(sCh1MC) ; maintain current ldi ZL,LOW(sCh1MC) rcall ChCurrent ; correct current to that value ChckStates6: lsr R1 ; channel mask next channel lsr R1 inc R0 ; next channel mov rmp,R0 ; channel = 5? cpi rmp,5 brcc ChckStates7 ; yes, stop rjmp ChckStates1 ; go on ChckStates7: ret ; ; Display result in hex on Uart ; DisplHex: cbr rFlgD,1<