我想在ATMEGA8中timer0的PWM模式下产生一个PWM波,如下图:
它具有 20% 的占空比,但不能单独使用 PWM 模式来实现。 我尝试在反向模式下使用快速 PWM 模式,并尝试检查 TCNT0 直到它达到 64H,这样我就可以在达到 64H 时清除 OC0 PIN。
我想知道当我手动清除 OC0 时此方法是否正常工作?
这是我的代码:
.DEF A = R16 ;GENERAL PURPOSE ACCUMULATOR
.ORG $0000
ON_RESET:
SBI DDRB,3 ;SET PORTB3(OC0) FOR OUTPUT
LDI A,0b01011011 ;SET TO FAST PWM MODE
OUT TCCR0,A ;SET PRESCALER/DIVIDER TO /32
LDI A,32 ;DIFFERENT VALUE
OUT OCR0,A ;FOR COMPARE
MAIN_LOOP:
PLOOP: IN A,TCNT0 ;COMPARE TCNT0
ANDI A,0x64H ;COMPARE TCNT0 TO 64 TO MAKE IT ZERO
BRNEQ PLOOP
CBI PINB,3
RJMP MAIN_LOOP;A CHECK FOR TIMER LOOP
最佳答案
AVR 中的 PWM 周期通常以定时器溢出开始(相位校正和相位/频率校正 PWM 除外)...换句话说,您可以控制占空比,但不能控制启动。在您的示例中 - 无论出于何种原因 - 您想要控制 PWM 周期的开始(定时器溢出后 32 小时)以及占空比(大约 FFh 的 20% ... 32 小时)。
所以你可能需要考虑
- 使用自由运行的定时器每 1/FFh 生成一次中断
- 使用一个 8 位寄存器,在每次调用中断期间递增该寄存器(它会在 FF 之后溢出……没关系)
- 如果该寄存器读取 32h 或 64h,则反转输出引脚(或如下设置/重置)
- 在 SEI 之前将输出引脚设置为 0 来初始化您的程序
我很快就劫持了我的 AT90USBKEY2 上的一个 PWM LED 设备 - 使用 AT90USB1287 处理器 - 并根据它进行了修改。到上面(抱歉,代码有点长:-o ...见下文)
编辑:
严格来说,这一切只有在您有同步点时才有意义……如果您单独查看 20% 波形,您无法确定它是否从时隙 0x00
开始。或0x32
...示波器始终在脉冲的上升(或下降)沿同步。因此,您需要通过在 PWM_SUBLEVEL
溢出时在不同引脚上输出脉冲来提供 PWM 帧开始的引用。 。使用来自另一个引脚的脉冲作为示波器的同步源,当您开始更改PWM_ON
时,您开始看到相位的移动。 .
/*
* AsmFile1.asm
*
* Created: 19.05.2015 22:01:49
* Author: MikeD
*/
.nolist
.include <usb1287def.inc>
.list
.def TMP1 = R16
.def TMP2 = R17
.def PWM_SUBLEVEL = R18
.def PWM_ON = R19
.def PWM_OFF = R20
.cseg
.org 0x0000
jmp V_RESET ; 1 $0000 RESET External pin, Power-on reset, Brown-out reset, Watchdog reset, and JTAG AVR reset
jmp V_NOINT ; 2 $0002 INT0 External Interrupt Request 0
jmp V_NOINT ; 3 $0004 INT1 External Interrupt Request 1
jmp V_NOINT ; 4 $0006 INT2 External Interrupt Request 2
jmp V_NOINT ; 5 $0008 INT3 External Interrupt Request 3
jmp V_NOINT ; 6 $000A INT4 External Interrupt Request 4
jmp V_NOINT ; 7 $000C INT5 External Interrupt Request 5
jmp V_NOINT ; 8 $000E INT6 External Interrupt Request 6
jmp V_NOINT ; 9 $0010 INT7 External Interrupt Request 7
jmp V_NOINT ; 10 $0012 PCINT0 Pin Change Interrupt Request 0
jmp V_NOINT ; 11 $0014 USB General USB General Interrupt request
jmp V_NOINT ; 12 $0016 USB Endpoint/Pipe USB ENdpoint/Pipe Interrupt request
jmp V_NOINT ; 13 $0018 WDT Watchdog Time-out Interrupt
jmp V_NOINT ; 14 $001A TIMER2 COMPA Timer/Counter2 Compare Match A
jmp V_NOINT ; 15 $001C TIMER2 COMPB Timer/Counter2 Compare Match B
jmp V_T2OVF ; 16 $001E TIMER2 OVF Timer/Counter2 Overflow
jmp V_NOINT ; 17 $0020 TIMER1 CAPT Timer/Counter1 Capture Event
jmp V_NOINT ; 18 $0022 TIMER1 COMPA Timer/Counter1 Compare Match A
jmp V_NOINT ; 19 $0024 TIMER1 COMPB Timer/Counter1 Compare Match B
jmp V_NOINT ; 20 $0026 TIMER1 COMPC Timer/Counter1 Compare Match C
jmp V_NOINT ; 21 $0028 TIMER1 OVF Timer/Counter1 Overflow
jmp V_NOINT ; 22 $002A TIMER0 COMPA Timer/Counter0 Compare Match A
jmp V_NOINT ; 23 $002C TIMER0 COMPB Timer/Counter0 Compare match B
jmp V_NOINT ; 24 $002E TIMER0 OVF Timer/Counter0 Overflow
jmp V_NOINT ; 25 $0030 SPI, STC SPI Serial Transfer Complete
jmp V_NOINT ; 26 $0032 USART1 RX USART1 Rx Complete
jmp V_NOINT ; 27 $0034 USART1 UDRE USART1 Data Register Empty
jmp V_NOINT ; 28 $0036 USART1TX USART1 Tx Complete
jmp V_NOINT ; 29 $0038 ANALOG COMP Analog Comparator
jmp V_NOINT ; 30 $003A ADC ADC Conversion Complete
jmp V_NOINT ; 31 $003C EE READY EEPROM Ready
jmp V_NOINT ; 32 $003E TIMER3 CAPT Timer/Counter3 Capture Event
jmp V_NOINT ; 33 $0040 TIMER3 COMPA Timer/Counter3 Compare Match A
jmp V_NOINT ; 34 $0042 TIMER3 COMPB Timer/Counter3 Compare Match B
jmp V_NOINT ; 35 $0044 TIMER3 COMPC Timer/Counter3 Compare Match C
jmp V_NOINT ; 36 $0046 TIMER3 OVF Timer/Counter3 Overflow
jmp V_NOINT ; 37 $0048 TWI 2-wire Serial Interface
jmp V_NOINT ; 38 $004A SPM READY Store Program Memory Ready
V_RESET:
; prepare stack ... special write procedure
ldi TMP1, low(ramend)
ldi TMP2, high(ramend)
out spl, TMP1
out sph, TMP2
; increase CLKIO from 1 to 8MHz ... special write procedure
ldi TMP1, 0b1000_0000
ldi TMP2, 0b0000_0000
sts CLKPR, TMP1
sts CLKPR, TMP2
; initialize variables
clr PWM_SUBLEVEL
ldi PWM_ON, 0x32
ldi PWM_OFF, 0x64
; prepare LED ports
; D2-RD on PORTD4
; D2-GN on PORTD5
; D5-RD on PORTD7
; D5-GN on PORTD6
ldi TMP1, 0b1111_0000
out DDRD, TMP1
; Timer2 (8bit) without prescaler in normal mode
; generates interrupt every 256 CPU clock cycles (32 us) for PWM sublevel
; we use this for PWM as Timer2 has the highest priority amongst timers
clr TMP1
sts TCCR2A, TMP1 ; normal mode, port pins disabled
ldi TMP1, (1 << CS20)
sts TCCR2B, TMP1 ; internal clock, no prescaler
ldi TMP1, (1 << TOIE2)
sts TIMSK2, TMP1 ; overflow interrupt enable
sei ; set general interupt enable flag
MAIN:
rjmp MAIN
V_T2OVF:
; fires every 32 us
inc PWM_SUBLEVEL ; overflows every 8.192 ms, f=122.07... Hz
cp PWM_SUBLEVEL, PWM_ON
breq GO_HI
cp PWM_SUBLEVEL, PWM_OFF
breq GO_LO
reti
GO_HI:
sbi PORTD, PORTD4
reti
GO_LO:
cbi PORTD, PORTD4
reti
V_NOINT:
; fire error LED ... if we get here something is wrong
sbi PIND, PIND7 ; invert output by writing 1 to input bit in output mode
reti
关于assembly - 如何在AVR中产生占空比为20%的PWM脉冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30239610/