附录2 SPWM程序
//ICC-AVR application builder : // Target : M8 // Crystal: 8.0000Mhz #include #include unsigned char i=0,k=0,out_date=0; /*unsigned char timer_long[40]={0x01,0x39, ;此段为测试输出,实际中不用 0x02,0x64, 0x03,0x84, 0x04,0x94, 0x05,0x86, 0x06,0x52, 0x06,0xf6, 0x07,0x6e, 0x07,0xb7, 0x07,0xd0, 0x07,0xd0, 0x07,0xb7, 0x07,0x6e, 0x06,0xf6, 0x06,0x52, 0x05,0x86, 0x04,0x94, 0x03,0x84, 0x02,0x64, 0x01,0x39 };*/ unsigned char timer_long[20]={ 0x01,0x37,//0x35, 0x02,0xc5,//0xc3, 0x03,0x7d,//0x7b, 0x03,0xb9,//0xb7, 0x03,0xdd,//0xdb, 0x03,0xdd,//0xdb, x03,0xb9,//0xb7, 0x03,0x7d,//0x7b, 0x02,0xc5,//0xc3, 0x01,0x37,//0x35, }; void port_init(void) { PORTB = 0xff; DDRB = 0xFF; PORTC = 0x00; //m103 output only DDRC = 0x00; PORTD = 0x00; DDRD = 0x00; } //TIMER1 initialize - prescale:1 // WGM: 0) Normal, TOP=0xFFFF // desired value: 0.125uSec // actual value: 0.125uSec (0.0%) void timer1_init(void) { TCCR1B = 0x00; //stop TCNT1H = 0xFF; //setup TCNT1L = 0xFF; OCR1AH = 0x00; OCR1AL = 0x01; OCR1BH = 0x00; OCR1BL = 0x01; ICR1H = 0x00; ICR1L = 0x01; TCCR1A = 0x00; TCCR1B = 0x01; //start Timer } #pragma interrupt_handler timer1_ovf_isr:9 void timer1_ovf_isr(void) { //TIMER1 has overflowed k++; if(k==2)k=0; if(k==1){ TCNT1H = 0xff-timer_long[2*i]; //reload counter high value TCNT1L = 0xff-timer_long[2*i+1]; //reload counter low value if(out_date==0) {PORTB =PORTB|0x01;PORTB =PORTB&0xfd;} else { PORTB =PORTB|0x02;PORTB =PORTB&0xfe;} i++;} else{ TCNT1H =0xfc+timer_long[2*i]; //reload counter high value TCNT1L =0xff+timer_long[2*i+1]; //reload counter low value //TCNT1L =0x19+timer_long[2*i+1]; //reload counter low value // TCNT1H =0xf8+timer_long[2*i]; //reload counter high value;16M // TCNT1L =0x2f+timer_long[2*i+1]; //reload counter low value //TCNT1H =0xe0+8*timer_long[2*i]; //reload counter high value // TCNT1L =0xbf+8*timer_long[2*i+1]; //reload counter low value if(out_date==0) {PORTB =PORTB&0xfe;PORTB =PORTB&0xfd;} else { PORTB =PORTB&0xfd;PORTB =PORTB&0xfe;} } if(i==10){i=0;out_date++;if(out_date==2){out_date=0;};}; } //call this routine to initialize all peripherals void init_devices(void) { //stop errant interrupts until set up CLI(); //disable all interrupts port_init(); timer1_init(); MCUCR = 0x00; GICR = 0x00; TIMSK = 0x04; //timer interrupt sources SEI(); //re-enable interrupts //all peripherals are now initialized } // void main(void) { init_devices(); //insert your functional code here... }
附录3 电压采集程序
;************************; ;模拟数据采集显示电路; ;************************; ;70H-77H存放采样值,78H-7BH存放显示数据,依次为个位、十位、百位、通道标志 ;************************************* ;* * ;* 主程序和中断程序入口 * ;* * ;************************************* ORG 0000H ;程序执行开始地址 LJMP START ;跳至START执行 ORG 0003H ;外中断0中断入口地址 LJMP INT0 ORG 0030H ;************************************* ;* * ;* 初始化程序中的各变量 * ;* * ;************************************* CLEARMEMIO: CLR A ; MOV P2,A ;P2口置0 MOV R0,#70H ;内存循环清0(70H-7BH) MOV R2,#0CH ; LOOPMEM: MOV @R0,A ; INC R0 ; DJNZ R2,LOOPMEM ; MOV A,#0FFH ; MOV P0,A ;P0、P1、P3端口置1 MOV P1,A ; MOV P3,A ; RET ;子程序返回 ;************************************; ; * 主 程 序 * ;*;*********************************; START: LCALL CLEARMEMIO ;初始化 MAIN: LCALL DISPLAY ;显示数据一次 LCALL TEST ;测量一次 AJMP MAIN ;返回MAIN循环 NOP ;PC值出错处理 NOP ;空操作 NOP ;空操作 LJMP START ;重新复位起动 DISPLAY: MOV R3,#08H ;8路信号循环显示控制 MOV R0,#70H ;显示数据初址(70H-77H) MOV 7BH,#00H ;显示通道路数(0-7) DISLOOP1: MOV A,@R0 ;显示数据转为三位十进制BCD码存入 MOV B,#100 ;7AH、79H、78H显示单元内 DIV AB ;显示数据除100 MOV 7AH,A ;商入7AH MOV A,#10 ;A放入数10 XCH A,B ;余数与数10交换 DIV AB ;余数除10 MOV 79H,A ;商入79H MOV 78H,B ;余数入78H MOV R2,#0FFH ;每路显示时间控制 4MS*255 DISLOOP2: LCALL DISP ;调四位LED显示程序 DJNZ R2,DISLOOP2 ;每路显示时间控制 INC R0 ;显示下一路 INC 7BH ;通道显示数值加1 DJNZ R3,DISLOOP1 ;8路显示未完转DISLOOP1再循环 RET ;8路显示完子程序结束 ; LED共阳显示子程序,显示内容在78H-7BH,数据在P1输出,列扫描在P3.0-P3.3 DISP: MOV R1,#78H ;赋显示数据单元首址 MOV R5,#0FEH ;扫描字 PLAY: MOV P1,#0FFH ;关显示 MOV A,R5 ;取扫描字 ANL P3,A ;开显示 MOV A,@R1 ;取显示数据 MOV DPTR,#TAB ;取段码表首址 MOVC A,@A+DPTR ;查显示数据对应段码 MOV P1,A ;段码放入P1口 LCALL DL1MS ;显示1MS INC R1 ;指向下一地址 MOV A,P3 ;取P3口扫描字 JNB ACC.3,ENDOUT ;四位显示完转ENDOUT结束 RL A ;扫描字循环左移 MOV R5,A ;扫描字放入R5暂存 MOV P3,#0FFH ;显示暂停 AJMP PLAY ;转PLAY循环 ENDOUT: MOV P3,#0FFH ;显示结束,端口置1 MOV P1,#0FFH RET ;子程序返回 ;LED数码显示管用共阳段码表,分别对应0-9,最后一个是"熄灭符" TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH ; 1MS延时子程序,LED显示用 DL1MS: MOV R6,#14H ; DL1: MOV R7,#19H DL2: DJNZ R7,DL2 DJNZ R6,DL1 RET ;模数转换测量子程序 TEST: CLR A ;清累加器A MOV P2,A ;清P2口 MOV R0,#70H ;转换值存放首址 MOV R7,#08H ;转换8次控制 LCALL TESTART ;启动测试 WAIT: JB P3.7,MOVD ;等A/D转换结束信号后转MOVD AJMP WAIT ;P3.7为0等待 TESTART: SETB P2.3 ;锁存测试通道地址 NOP ; 延时2微秒 NOP CLR P2.3 ;测试通道地址锁存完毕 SETB P2.4 ; 启动测试,发开始脉冲 NOP ; 延时2微秒 NOP CLR P2.4 ; 发启动脉冲完毕 NOP ;延时4微秒 NOP NOP RET ;子程序调用结束 ; 取A/D转换数据至70H-77H内存单元 MOVD: SETB P2.5 ;8090输出允许 MOV A,P0 ;将A/D转换值移入A MOV @R0,A ;放入内存单元 CLR P2.5 ;关闭8090输出 INC R0 ;内存地址加1 MOV A,P2 ;通道地址移入A INC A ;通道地址加1 MOV P2,A ; 通道地址送8090 CLR C ;清进位标志 CJNE A,#08H,TESTCON ; 通道地址不等于8转TESTCONT再测试 JC TESTCON ; 通道地址小于8转TESTCONT再测试 CLR A ; 大于或等于8,A/D转换结束恢复端口 MOV P2,A ; P2口置0 MOV A,#0FFH ; MOV P0,A ; P0口置1 MOV P1,A ; P1口置1 MOV P3,A ; P3口置1 RET ; 取A/D转换数据结束 TESTCON: LCALL TESTART ; 再发测试启动脉冲 LJMP WAIT ; 跳至WAIT等待A/D转换结束信号 END ; 程序结束