Giter Club home page Giter Club logo

Comments (3)

windelbouwman avatar windelbouwman commented on June 19, 2024 1

Would it be possible to hookup a DMA transfer to the PWM peripheral, so that for each PWM cycle, a new timer reload value is selected?

Ideally one would setup a memory buffer with the bit pattern specified as reload values for the 0 and 1 bits, and then trigger a DMA transfer, and stop the PWM afterwards.

from stm32l4xx-hal.

oralian avatar oralian commented on June 19, 2024

For anyone interested, here's the code using a DMA transfer to the PWM peripheral in the case for a WS2812b LED strip!

#[entry]
fn main() -> ! {
    // setup the board
    let dp = stm32l4xx_hal::stm32::Peripherals::take().unwrap();

    // setup the peripherals
    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr); // sets by default the clock to 16mhz ?!
    let _channels = dp.DMA1.split(&mut rcc.ahb1);

    // setup the PWM
    let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
    let c1 = gpioa.pa0.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper).into_af1(&mut gpioa.moder, &mut gpioa.afrl);
    let mut pwm = dp.TIM2.pwm(c1, 800.khz(), clocks, &mut rcc.apb1r1);
    let max = pwm.get_max_duty();

    let one_duty = (max * 90 / 125) as u32;
    let zero_duty = (max * 35 / 125) as u32;
    let buffer: [u32; 122] = [
        one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty,
        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,
        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,

        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,
        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,
        one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty,

        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,
        one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty, one_duty,
        zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty, zero_duty,

        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ];

    pwm.set_duty(0);
    pwm.enable();

    unsafe {
        let tim2 = &*TIM2::ptr(); // general timer 2 pointer
        let rcc_ptr = &*RCC::ptr(); // RCC pointer
        let dma1 = &*DMA1::ptr(); // DMA 1 pointer
    
        rcc_ptr.ahb1enr.modify(|_, w| w.dma1en().set_bit()); // enable DMA1 clock: peripheral clock enable register

        // timer for DMA configuration
        tim2.dier.write(|w| w.tde().set_bit()); // enable DMA trigger
        tim2.dier.write(|w| w.ude().set_bit()); // enable update DMA request

        let _a = &tim2.ccr1 as *const _ as u32; // very different from 0x4000_0034

        // DMA configuration
        dma1.cselr.write(|w| w.c2s().bits(0b0100)); // set CxS[3:0] to 0100 to map the DMA request to timer 2 channel 1
        dma1.cpar2.write(|w| w.pa().bits(0x4000_0034)); // set the DMA peripheral address register to the capture/compare 1 of TIM2
        dma1.cmar2.write(|w| w.ma().bits(buffer.as_ptr() as u32)); // write the buffer to the memory adress
        dma1.cndtr2.write(|w| w.ndt().bits(buffer.len() as u16)); // number of data to transfer register    
        dma1.ccr2.modify(|_, w| w
            .mem2mem().clear_bit() // memory-to-memory disabled
            .pl().high() // set highest priority
            .msize().bits(2) // size in memory of each transfer: b10 = 32 bits long
            .psize().bits(2) // size of peripheral: b10 = 32 bits long --> 32 or 16 ?? 
            .minc().set_bit() // memory increment mode enabled
            .pinc().clear_bit() // peripheral increment mode disabled
            .circ().set_bit() // circular mode: the dma transfer is repeated automatically when finished
            .dir().set_bit() // data transfer direction: 1 = read from memory
            .teie().set_bit() // transfer error interrupt enabled
            .htie().set_bit() // half transfer interrupt enabled
            .tcie().set_bit() // transfer complete interrupt enabled
            .en().set_bit() // channel enable
        );
    }

    loop {
    }
}

from stm32l4xx-hal.

windelbouwman avatar windelbouwman commented on June 19, 2024

Note there is an examples folder located in this repository, it might make sense to put this particular example in there: https://github.com/stm32-rs/stm32l4xx-hal/tree/master/examples

from stm32l4xx-hal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.