Вот такая заготовка для всяких поделок типа вольтметров, счетчиков, датчиков и т.д. и т.п.
А вот пример кода для вольт-амперметра с программным шимом и опросом энкодера:
@device = pic16F676, intrc_osc_noclkout, wdt_on, mclr_off, protect_off osccal = %11111100 enc1 var porta.5 enc2 var porta.4 butt var porta.3 D_C var portc.3 rst var portc.2 SDIN var portc.4 SCK var portc.5 shim var porta.2 voltm con 0 'an0 ampm con 1 'an1 define adc_bits 10 define adc_clock 3 define adc_sampleus 50 adval var word trisa=%00111011 trisc=0 CMCON = 7 ANSEL = %00000011 ' an1, AN0 adcon0=%10000000 ' правое выравнивание, опорное - питание LcdReg var byte x var byte y var byte t var byte e var byte z var byte Offset var byte Char var byte a var byte tmpshim var byte shcount var byte portc = 0 counter var word encstate var byte new var byte ioca = %00111000 wpua = %00110100 tmr0 = 255 INTCON = %10101000 OPTION_REG = %00000000 counter = 0 tmpshim = 0 shcount = 255 on interrupt goto encoder DATA @0,$3E,$51,$49,$45,$3E,_ ';// 0 $00,$42,$7F,$40,$00,_ ';// 1 $42,$61,$51,$49,$46,_ ';// 2 $21,$41,$45,$4B,$31,_ ';// 3 $18,$14,$12,$7F,$10,_ ';// 4 $27,$45,$45,$45,$39,_ ';// 5 $3C,$4A,$49,$49,$30,_ ';// 6 $01,$71,$09,$05,$03,_ ';// 7 $36,$49,$49,$49,$36,_ ';// 8 $06,$49,$49,$29,$1E,_ ';// 9 $08,$08,$3E,$08,$08,_ ';// + $08,$08,$08,$08,$08,_ ';// - $00,$60,$60,$00,$00,_ ';// . $3F,$40,$40,$40,$3F,_ ';// U $7E,$11,$11,$11,$7E,_ ';// A $00,$41,$7F,$41,$00,_ ';// I $1F,$20,$40,$20,$1F ';// V RST = 1 LcdReg = %00100001 'LCD Extended Commands. call PrintCtrlLcd LcdReg = 228 'Set LCD Vop (Contrast). call PrintCtrlLcd LcdReg = %00000111 'Set Temp coefficent. call PrintCtrlLcd LcdReg = %00010011 'LCD bias mode 1:48. call PrintCtrlLcd LcdReg = %00100000 'LCD Standard Commands, Horizontal addressing mode. call PrintCtrlLcd LcdReg = %00001100 call PrintCtrlLcd call CursorHome Call ClearLcd Main: y = 1 x = 0 Char = 13 ' "U" call PrintWChar x = 24 adcin voltm, adval adval = adval*3 Char = (adval dig 3) ' десятые call PrintWChar Char = (adval dig 2) ' единицы call PrintWChar Char = 12 ' точка call PrintWChar Char = (adval dig 1) ' десятые call PrintWChar Char = (adval dig 0) ' сотые call PrintWChar x = 0 y = 3 Char = 15 ' "I" call PrintWChar x = 24 adcin ampm, adval adval = adval*3 Char = (adval dig 3) ' единицы call PrintWChar Char = 12 ' точка call PrintWChar Char = (adval dig 2) ' десятые call PrintWChar Char = (adval dig 1) ' сотые call PrintWChar Char = (adval dig 0) ' тысячн call PrintWChar y = 5 x = 0 Char = (counter dig 4) ' десятые call PrintChar Char = (counter dig 3) ' десятые call PrintChar Char = (counter dig 2) ' точка call PrintChar Char = (counter dig 1) ' десятые call PrintChar Char = (counter dig 0) ' сотые call PrintChar 'PAUSE 500 Goto main disable encoder: if intcon.0 = 1 then intcon.0 = 0 new = enc1 + enc2 * 2 if encstate = 2 then if new = 3 then counter = counter + 1 if new = 0 then counter = counter - 1 endif if encstate = 0 then if new = 2 then counter = counter + 1 if new = 1 then counter = counter - 1 endif if encstate = 1 then if new = 0 then counter = counter + 1 if new = 3 then counter = counter - 1 endif if encstate = 3 then if new = 1 then counter = counter + 1 if new = 2 then counter = counter - 1 endif encstate = new counter = counter & %0000001111111111 endif if intcon.2 = 1 then intcon.2 = 0 tmr0 = 255 shcount = shcount - 1 if shcount = 0 then tmpshim = counter >> 2 if tmpshim > 0 then shim = 1 tmpshim = tmpshim - 1 else shim = 0 endif endif resume enable ' Перевод курсора x=0..83 y=0..5 CursorHome: x = 0 y = 0 SetCursor: LcdReg = %10000000 + x ' cursor X call PrintCtrlLcd LcdReg = %01000000 + y ' cursor Y call PrintCtrlLcd return PrintChar: offset = Char * 5 call SetCursor for a = 1 to 5 read offset, LcdReg call PrintDataLcd offset = offset + 1 next a x = x + 6 return ' печать символа удвоенного размера PrintWChar: offset = Char * 5 for a = 1 to 5 read offset, z t = (z & 1)*3 t = t|((z & 2)*6) t = t|((z & 4)*12) t = t|((z & 8)*24) call SetCursor LcdReg = t call PrintDataLcd LcdReg = t call PrintDataLcd z = z >> 4 t = (z & 1)*3 t = t|((z & 2)*6) t = t|((z & 4)*12) t = t|((z & 8)*24) y = y + 1 call SetCursor LcdReg = t call PrintDataLcd LcdReg = t call PrintDataLcd offset = offset + 1 x = x + 2 y = y - 1 next a x = x + 2 return ' очистка китайца (708 нулевых байта) ClearLcd: D_C = 1 LcdReg = 0 for t = 0 to 235 for a = 0 to 2 call PrintDataLcd next a next t Return ' отправка данных/команд на lcd PrintCtrlLcd: D_C = 0 PrintDataLcd: for e = 1 to 8 SDIN = LcdReg.7 LcdReg = LcdReg << 1 SCK = 1 SCK = 0 next e D_C = 1 return end
вольтметр висит на AN0, амперметр на AN1, вывод шима с RA2. частотой програмный шим не блещет, поэтому фильтр я на него вешал из 2 резисторов на 4.7к и 2 емкостей 10 мкФ...