PIC单片机实现带反馈控制的PWM信号发生器源码
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://techlife.blog.51cto.com/212583/49888 |
这个实现了一个带反馈控制的PWM发生器。PWM信号的占空比由电位器决定,电位器上的电压被采样后,与PWM信号经过低通滤波的电压比较,根据比较的结果调整占空比,从而实现用电位器控制占空比。 LIST p=PIC16F877A,r=hex ;microcontroller & base INCLUDE "P16F877A.inc" ;register memory mapping file ;************************ ; global variables ;************************ i equ 0x21 ;general purpose counter 1 j equ 0x22 ;general purpose counter 2 pot_ana_value equ 0x23 ;Analog value of the potentiometer pwm_ana_value equ 0x24 ;Analog value of the PWM output after low filtering #define timer_trigger 0x25, 0 ;This bit indicating the timer has been triggered w_temp equ 0x26 ; temp variable for W register status_temp equ 0x27 ; status variable for STATUS register temp equ 0x28 ; general temp variable ;************************ ; port definitions ;************************ #define led_data PORTD ;portD outputs 7-segment data #define led_pot_high PORTB, 0 ;portB.0 selects high 4-bit value of pot #define led_pot_low PORTB, 1 ;portB.1 selects low 4-bit value of pot #define led_pwm_high PORTB, 2 ;portB.2 selects high 4-bit value of pwm #define led_pwm_low PORTB, 3 ;portB.3 selects low 4-bit value of pwm #define led_inc PORTB, 4 ;portB.4 drive the LED indicating PWM ;duty cycle increasing. #define led_dec PORTB, 5 ;portB.5 drive the LED indicating PWM ;duty cycle decreasing. ;************************ ; reload value of TMR0 ; Timer 0 Interval = 5000 us ; 64 * ( 256 - TMR0 ) = 5000, TMR0 = 178 (0xB2) ;************************ tmr0_reload equ 0xB2 ;************************ ; 7-segment LED definitions ; a ; +----------+ ; | | ; f| |b ; | g | ; +----------+ ; | | ; e| |c ; | | ; +----------+ o dp ; d ;************************ LED_SEGa equ 0x40 ;7-segment display segment A LED_SEGb equ 0x20 ;7-segment display segment B LED_SEGc equ 0x10 ;7-segment display segment C LED_SEGd equ 0x08 ;7-segment display segment D LED_SEGe equ 0x04 ;7-segment display segment E LED_SEGf equ 0x02 ;7-segment display segment F LED_SEGg equ 0x01 ;7-segment display segment G LED_SEGdp equ 0x80 ;not used LED_BLANK equ 0x00 ;**************************************************************** ;reset vector ;**************************************************************** ResetVec: org 0x0000 ;reset vector address goto Start ;start program execution org 0x0004 Tmr0IntServ: ; Timer 0 interrupt service routing movwf w_temp ; save W register swapf STATUS, W clrf STATUS movwf status_temp ; save STATUS register bcf INTCON, T0IF ; clear Timer 0 interrupt flag bsf timer_trigger movlw tmr0_reload ; reload timer 0 movwf TMR0 swapf status_temp, W movwf STATUS ; restore STATUS register swapf w_temp, F swapf w_temp, W ; restore W register retfie Start: org 0x0100 ;start of program goto SysInit ;**************************************************************** ; LED DISPLAY DECODER FROM BINARY TO 7-SEGMENT ; the hex value to be displayed is stored in W before calling this ; function. The function will return the output value of LED in W ;**************************************************************** LEDDecoder: addwf PCL,f ;W DISPLAY retlw LED_SEGa|LED_SEGb|LED_SEGc|LED_SEGd|LED_SEGe|LED_SEGf ;0 - "0" retlw LED_SEGb|LED_SEGc ;1 - "1" retlw LED_SEGa|LED_SEGb|LED_SEGd|LED_SEGe|LED_SEGg ;2 - "2" retlw LED_SEGa|LED_SEGb|LED_SEGc|LED_SEGd|LED_SEGg ;3 - "3" retlw LED_SEGb|LED_SEGc|LED_SEGf|LED_SEGg ;4 - "4" retlw LED_SEGa|LED_SEGc|LED_SEGd|LED_SEGf|LED_SEGg ;5 - "5" retlw LED_SEGa|LED_SEGc|LED_SEGd|LED_SEGe|LED_SEGf|LED_SEGg ;6 - "6" retlw LED_SEGa|LED_SEGb|LED_SEGc ;7 - "7" retlw LED_SEGa|LED_SEGb|LED_SEGc|LED_SEGd|LED_SEGe|LED_SEGf|LED_SEGg ;8 - "8" retlw LED_SEGa|LED_SEGb|LED_SEGc|LED_SEGd|LED_SEGf|LED_SEGg ;9 - "9" retlw LED_SEGa|LED_SEGb|LED_SEGc|LED_SEGe|LED_SEGf|LED_SEGg ;0xA - "A" retlw LED_SEGc|LED_SEGd|LED_SEGe|LED_SEGf ;0xB - "b" retlw LED_SEGa|LED_SEGd|LED_SEGe|LED_SEGf ;0xC - "C" retlw LED_SEGb|LED_SEGc|LED_SEGd|LED_SEGe|LED_SEGg ;0xD - "d" retlw LED_SEGa|LED_SEGd|LED_SEGe|LED_SEGf|LED_SEGg ;0xE - "E" retlw LED_SEGa|LED_SEGe|LED_SEGf|LED_SEGg ;0xF - "F" retlw LED_BLANK ;0x10- " " ;**************************************************************** ; System initialization ;**************************************************************** SysInit: bcf STATUS, RP1 bsf STATUS, RP0 clrf TRISB ;portB output clrf TRISC ;portC output clrf TRISD ;portD output movlw 0xff movwf TRISA ;portA input bcf STATUS, RP0 ;set initial value of the I/O ports clrf PORTB clrf PORTD clrf PORTC bcf timer_trigger ; Timer 0 config movlw tmr0_reload ; timer 0 initial value movwf TMR0 bsf STATUS, RP0 movlw 0x05 ; timer 0 freq div = 64, use internal clock movwf OPTION_REG ; PWM config movlw 0xff ; PWM cycle = 256us movwf PR2 bcf STATUS, RP0 movlw 0x80 ; CCP1RL initial value, 50% duty cycle movwf CCPR1L movlw 0x0C ; PWM mode for CCP1 movwf CCP1CON movlw 0x04 ; T2 control: 1:1 freq div, enable T2 movwf T2CON ; ADC config bsf STATUS, RP0 clrf ADCON1 ; left alignment, 8 analog channel bcf STATUS, RP0 movlw 0x81 ; Focs/32 A/D clock freq, enable ADC movwf ADCON0 ; Interrupt config movlw 0xA0 movwf INTCON ; enable Timer 0 interrupt ;**************************************************************** ; The main loop of the program ;**************************************************************** Mainloop: btfsc timer_trigger call AdjustPWM call ScanLED goto Mainloop ;endless loop ;**************************************************************** ; Adjust PWM duty cycle ;**************************************************************** AdjustPWM: bcf timer_trigger call UpdateAnalogValue movf pot_ana_value, W subwf pwm_ana_value, W btfss STATUS, Z goto need_adjustment no_adjustment: bcf led_inc ; equal, no adjustment needed bcf led_dec ; turn-off the LEDs return need_adjustment: btfss STATUS, C goto need_decreament movlw 0xff ; need increament subwf CCPR1L, W btfsc STATUS, Z goto no_adjustment ; if CCPR1L = 0xff, can't increase any more bsf led_inc bcf led_dec incf CCPR1L, F return need_decreament movlw 0x00 subwf CCPR1L, W btfsc STATUS, Z goto no_adjustment ; if CCPR1L = 0x00, can't decrease any more bsf led_dec bcf led_inc decf CCPR1L, F return ;**************************************************************** ; SCAN the 7-Segment LEDs ;**************************************************************** ScanLED: movf pot_ana_value, W andlw 0x0f ; low 4-bit call LEDDecoder movwf led_data ; output value bsf led_pot_low movlw 0x32 call Delayx10us ; delay 500us bcf led_pot_low swapf pot_ana_value, W ; high 4-bit pot analog value andlw 0x0f call LEDDecoder movwf led_data bsf led_pot_high movlw 0x32 call Delayx10us bcf led_pot_high movf pwm_ana_value, W ; low 4-bit pwm analog value andlw 0x0f call LEDDecoder movwf led_data bsf led_pwm_low movlw 0x32 call Delayx10us bcf led_pwm_low swapf pwm_ana_value, W ; high 4-bit pwm analog value andlw 0x0f call LEDDecoder movwf led_data bsf led_pwm_high movlw 0x32 call Delayx10us bcf led_pwm_high return ;**************************************************************** ; Delay W x 10 us ;**************************************************************** Delayx10us: movwf i Delay_loop: nop nop nop nop nop nop nop nop decfsz i, F goto Delay_loop return ;**************************************************************** ; Update Analog value using A/D conversion ;**************************************************************** UpdateAnalogValue: bcf ADCON0, CHS0 ; select RA0 for analog input, POT value movlw 0x03 call Delayx10us ; delay for 30us bsf ADCON0, GO_DONE UAV_loop1: btfsc ADCON0, GO_DONE ; wait for A/D conversion goto UAV_loop1 movf ADRESH, W movwf pot_ana_value ; update value movlw 0x03 ; delay 30us for next conversion call Delayx10us bsf ADCON0, CHS0 ; select RA1 for analog input, PWM value movlw 0x03 call Delayx10us ; delay for 30us bsf ADCON0, GO_DONE UAV_loop2: btfsc ADCON0, GO_DONE ; wait for A/D conversion goto UAV_loop2 movf ADRESH, W movwf pwm_ana_value ; update value return END 本文出自 “techlife” 博客,请务必保留此出处http://techlife.blog.51cto.com/212583/49888 本文出自 51CTO.COM技术博客 |



ypixunil
博客统计信息
热门文章
最新评论
友情链接