我已将STM32F767ZI上的RCC设置为48 MHz(当设置为更高频率时会发生错误,尽管在具有相同设置的CubeMX中没有错误)。
rcc.cr.modify(|_, w| w.hsebyp().set_bit());
rcc.cr.modify(|_, w| w.hseon().on());
while rcc.cr.read().hserdy().is_not_ready() {}
println!("{:b}", rcc.cr.read().bits());
println!("Hse ready");
rcc.pllcfgr.modify(|_, w| w.pllsrc().hse());
rcc.pllcfgr.modify(unsafe {|_, w| w.pllm().bits(4)});
rcc.pllcfgr.modify(unsafe {|_, w| w.plln().bits(96)});
rcc.pllcfgr.modify(|_, w| w.pllp().div4());
rcc.cr.modify(|_, w| w.pllon().on());
while rcc.cr.read().pllrdy().is_not_ready() {}
println!("Pll ready");
rcc.cfgr.modify(|_, w| w.sw().pll());
while !rcc.cfgr.read().sws().is_pll() {}
println!("pll selectected");
当 PWM 以 2 MHz 运行时,一切正常:
tim.arr.write(|w| w.bits(23));
和 let dma_buf = [8, 12, 12, 16, 0, 0, 0, 0];
2 MHz 的 PWM 脉冲
但是如果 PWM 以 4 MHz 运行,则第二个脉冲会重复
tim.arr.write(|w| w.bits(11));
和 let dma_buf = [4, 6, 6, 8, 0, 0, 0, 0];
4 Mhz的 PWM 脉冲,即对应于 dma_buf = [4, 6, 6, 6, 6, 8, 0, 0, 0, 0];
定时器和dma配置如下:
unsafe {
tim.arr.write(|w| w.bits(11)); // frequency
tim.ccr1().write(|w| w.bits(0));// duty cycle
}
// clear enable to zero just to be sure
tim.ccmr1_output().modify(|_, w| w.oc1ce().clear_bit());
//enable preload
tim.ccmr1_output().modify(|_, w| w.oc1pe().enabled());
// set pwm mode 1
tim.ccmr1_output().modify(|_, w| w.oc1m().pwm_mode1());
// enable output
tim.ccer.write(|w| w.cc1e().set_bit());
// enable auto-reload
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.dier.modify(|_, w| w.ude().set_bit());
tim.dier.modify(|_, w| w.cc1de().set_bit());
tim.dier.modify(|_, w| w.tde().set_bit());
// enable update generation - needed at first start
tim.egr.write(|w| w.ug().set_bit());
tim.egr.write(|w| w.ug().set_bit());
// start pwm
tim.cr1.modify(|_, w| w.cen().set_bit());
unsafe {
let ccr1_addr = tim.ccr1() as *const _ as u32;
let dma_buf = [4, 6, 6, 8, 0, 0, 0, 0];
dma1.st[4].m0ar.write(|w| w.m0a().bits(dma_buf.as_ptr() as u32));
dma1.st[4].ndtr.write(|w| w.ndt().bits(dma_buf.len() as u16));
dma1.st[4].par.write(|w| w.pa().bits(ccr1_addr));
dma1.st[4].cr.reset();
dma1.st[4].cr.modify(|_, w| w
.chsel().bits(5)
.mburst().single()
.pburst().single()
.pl().high()
.msize().bits32()
.psize().bits32()
.minc().set_bit()
.pinc().clear_bit()
.circ().enabled()
.dir().memory_to_peripheral()
.teie().set_bit()
.htie().set_bit()
.tcie().set_bit()
.en().enabled()
);
}
补救办法很简单,不要从CC触发DMA,而是从Update触发DMA,即不要设置CC1DE,而是设置UDE。 并选择设置 TIMx_UP 的 Stream。我还将 DMAR 地址而不是 CCR1 地址写入 PAR。
unsafe {
tim.arr.write(|w| w.bits(17)); // frequency
tim.ccr1().write(|w| w.bits(0));// duty cycle
}
// clear enable to zero just to be sure
tim.ccmr1_output().modify(|_, w| w.oc1ce().clear_bit());
//enable preload
tim.ccmr1_output().modify(|_, w| w.oc1pe().enabled());
// set pwm mode 1
tim.ccmr1_output().modify(|_, w| w.oc1m().pwm_mode1());
// enable output
tim.ccer.write(|w| w.cc1e().set_bit());
// enable auto-reload
tim.cr1.modify(|_, w| w.arpe().set_bit());
tim.dier.modify(|_, w| w.ude().set_bit());
tim.dier.modify(|_, w| w.cc1de().clear_bit());
tim.dcr.modify(|_, w| w.dba().bits(13));
// enable update generation - needed at first start
tim.egr.write(|w| w.ug().set_bit());
tim.egr.write(|w| w.ug().set_bit());
// start pwm
tim.cr1.modify(|_, w| w.cen().set_bit());
unsafe {
let dmar_addr = tim.dmar.as_ptr() as u32;
let dma_buf = [6, 9, 6, 9, 6, 9, 0, 0, 0];
dma1.st[2].m0ar.write(|w| w.m0a().bits(dma_buf.as_ptr() as u32));
dma1.st[2].ndtr.write(|w| w.ndt().bits(dma_buf.len() as u16));
dma1.st[2].par.write(|w| w.pa().bits(dmar_addr));
dma1.st[2].cr.reset();
dma1.st[2].cr.modify(|_, w| w
.chsel().bits(5)
.mburst().single()
.pburst().single()
.pl().high()
.msize().bits32()
.psize().bits32()
.minc().set_bit()
.pinc().clear_bit()
.circ().enabled()
.dir().memory_to_peripheral()
.teie().set_bit()
.htie().set_bit()
.tcie().set_bit()
.en().enabled()
);
}