PIC单片机两路PWM输出程序
LIST P=16f877A
#include \"p16f877a.inc\" ;定义所用单片机的头文件
;******************************************************************** ***********
;************************************ Count EQU 20H Count1 EQU 21H Count2 EQU 22H KEYRES EQU 23H ADKEYH EQU 24H L_R EQU 25H DLY1 EQU 26H DLY2 EQU 27H CNT EQU 28H INC_F EQU 29H CNT1 EQU 2AH INC_F1 EQU 2BH ORG 000H GOTO START NOP
START CALL InitPWM12 CALL InitADKEY MAIN
CALL GetADKEY GOTO MAIN
;************************************ InitADKEY ;A/D 转换初始化子程序 MOVLW 0X41
MOVWF ADCON0 ;选择A/D 通道为RA0,打开A/D 转换器 ;AD 转换时钟为FOSC/8 BSF STATUS,RP0 MOVLW 0X02
MOVWF ADCON1 ;转换结左移,及ADRESL寄存器的低6 位为\"0\"
BSF TRISA,0 ;且把RA0 口设置为模拟量输入方式;设置RA0 为输入方式
BCF STATUS,RP0 RETURN
;************************************ GetADKEY ;读取键值处理子程序 BSF ADCON0,GO ;启动AD转换 BTFSC ADCON0,GO ;等待A/D转换结束 GOTO $-1
MOVF ADRESH,W ;读取并存储A/D 转换结果
MOVWF ADKEYH ;判断键值1~9,若无键按下,认为键值为0 MOVLW 0X31 ; MOVWF KEYRES
KEY1 MOVLW 0XCB ;CC为S1按下对应A/D转换数字量的高8位
SUBWF ADKEYH,W ;比较阈值设为CB可增强抗干扰能力 BTFSS STATUS,C ;采用逐键比较判断 GOTO KEY2 GOTO KEYOUT KEY2 INCF KEYRES,F
MOVLW 0XA8 ;A9为S2按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY3
CALL DEC1 GOTO KEYOUT KEY3 INCF KEYRES,F
MOVLW 0X8F ;90为S3按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY4 CALL INC1 GOTO KEYOUT KEY4 INCF KEYRES,F
MOVLW 0X7D ;7E为S4按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY5 GOTO KEYOUT KEY5 INCF KEYRES,F
MOVLW 0X6F ;70为S5按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY6 CALL DEC2 GOTO KEYOUT KEY6 INCF KEYRES,F
MOVLW 0X63 ;为S6按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY7 CALL INC2 GOTO KEYOUT KEY7 INCF KEYRES,F
MOVLW 0X5A ;5B为S7按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY8 GOTO KEYOUT KEY8 INCF KEYRES,F
MOVLW 0X53 ;54为S8按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY9 GOTO KEYOUT KEY9 INCF KEYRES,F
MOVLW 0X4C ;4D为S9按下对应A/D转换数字量的高8位 SUBWF ADKEYH,W BTFSS STATUS,C GOTO KEY0 GOTO KEYOUT
KEY0 MOVLW 0x30 ;无键按下,返回30作为主函数判断有无键按下的设定值
MOVWF KEYRES ;也可以设定其他不与键值冲突的数值KEYOUT RETURN
;******************************************************************* ;递增递减PWM1
INC1 INCF CNT,1 MOVLW 03H
ANDWF CNT,1 ;屏蔽高六位 BCF CCP1CON,4 BCF CCP1CON,5 SWAPF CNT,W ADDWF CCP1CON,F
MOVLW 03H SUBWF CNT,F BTFSS STATUS,Z GOTO KEYOUT BCF CCP1CON,4 BCF CCP1CON,5 INCF CCPR1L,F ;脉宽递增
COMF CCPR1L,W ;检测当前值是最亮态否?
BTFSC STATUS,Z ;最亮时CCPR1L=FFH,取反得00H,Z=1 INCF INC_F,F ;是!递增标志位取反 RETURN ;返回 DEC1 DECF CNT,1 MOVLW 03H
ANDWF CNT,1 ;屏蔽高六位 BCF CCP1CON,4 BCF CCP1CON,5 SWAPF CNT,W ADDWF CCP1CON,F MOVLW 00H SUBWF CNT,F BTFSS STATUS,Z GOTO KEYOUT BCF CCP1CON,4 BCF CCP1CON,5
DECF CCPR1L,F ;脉宽递减
BTFSC STATUS,Z ;检测最暗否?最暗时CCPR1L=00H,Z=1 INCF INC_F,F ;是!递增标志位取反 RETURN ;返回
;******************************************************************* ;递增递减PWM2
INC2 INCF CNT1,1 MOVLW 03H
ANDWF CNT1,1 ;屏蔽高六位 BCF CCP2CON,4 BCF CCP2CON,5 SWAPF CNT1,W ADDWF CCP2CON,F MOVLW 03H SUBWF CNT1,F BTFSS STATUS,Z GOTO KEYOUT BCF CCP2CON,4 BCF CCP2CON,5 INCF CCPR2L,F ;脉宽递增
COMF CCPR2L,W ;检测当前值是最亮态否?
BTFSC STATUS,Z ;最亮时CCPR1L=FFH,取反得00H,Z=1 INCF INC_F1,F ;是!递增标志位取反 RETURN ;返回 DEC2 DECF CNT1,1 MOVLW 03H
ANDWF CNT1,1 ;屏蔽高六位 BCF CCP2CON,4 BCF CCP2CON,5 SWAPF CNT1,W ADDWF CCP2CON,F MOVLW 00H SUBWF CNT1,F BTFSS STATUS,Z GOTO KEYOUT BCF CCP2CON,4
BCF CCP2CON,5
DECF CCPR2L,F ;脉宽递减
BTFSC STATUS,Z ;检测最暗否?最暗时CCPR1L=00H,Z=1 INCF INC_F1,F ;是!递增标志位取反 RETURN ;返回
;******************************************************************* ;初始化PWM
InitPWM12
BSF STATUS,RP0 ;选bank1
MOVLW B'11111001' ;设置CCP1和RC2脚位输出 MOVWF TRISC
MOVLW 0XFF ;设定PWM周期为最大值FFH MOVWF PR2
MOVWF INC_F ;设置递增标志位 BCF STATUS,RP0 ;选bank0 MOVLW 0X0C ;设定1模块位: MOVWF CCP1CON ;PWM输出 MOVWF CCP2CON ;PWM输出 CLRF CCPR1L ;脉宽清0 CLRF CCPR2L ;脉宽清0
CLRF T2CON ;设定TMR2:后分频比1:1,预分频比1:1;暂时不开启BSF T2CON,TMR2ON ;启TMR2
RETURN
;*******************************************************************
;* Delay - 延时子程序
;******************************************************************* Delay ; call指令占用2个指令周期
clrf Count ; 清Count占用1个指令周期 Dloop
decfsz Count,f ; 这两行指令将延时 goto Dloop ; (256 * 3) -1 个指令周期 return ; return占用2个指令周期
;*******************************************************************
;*
LongDelay
-
长
延
时
子
程
序
* ;******************************************************************* LongDelay ; call指令占用2个指令周期
clrf Count ; 清Count占用1个指令周期 clrf Count1 ; 清Count1占用1个指令周期 movlw 0x03 ;占用1个指令周期 movwf Count2 ;占用1个指令周期 LDloop
decfsz Count,f ; 这两行指令将延时 goto LDloop ; (256 * 3) -1 个指令周期 decfsz Count1,f goto LDloop decfsz Count2,f goto LDloop return
;100ms延时子程序 DELAY1 MOVLW 0FFH MOVWF DLY1 LP0 M OVLW 07FH MOVWF DLY2 LP1 DECFSZ DLY2,F GOTO LP1 DECFSZ DLY1,F GOTO LP0 RETURN
END