Re: [Zephyr-users] Buggy PWM driver for nRF52
Felipe Neves <ryukokki.felipe@...>
Hello guys. @Vikrant you are right, the current implementation of nrf pwm's driver uses a software based PWM combined with the PPI./* pwm output pin */ #define PWM_OUT_PIN (0 | 31) /* pwm frequency and clk in Hz */ #define PWM_FREQUENCY 1000 #define PWM_CLK 8000000 #define PWM_TOP_VALUE_FIX (PWM_CLK / PWM_FREQUENCY) #define PWM_MAX_DUTY 0.30f /* 30 % */ #define PWM_MIN_DUTY 0.05 /* 5% */ #define PWM_PERCENT_RESOLUTION 0.0125 /* % */ /* polarity to be added on pwm sequencer */ #define PWM_POLARITY_OFFSET (1 << 15)
/** * temp_pwm_init() * * @brief inits the pwm controller and route it to the heater * @param * @return */ static void temp_pwm_init(void) { NRF_PWM0->PSEL.OUT[0] = PWM_OUT_PIN; /* pwm in upmode */ NRF_PWM0->MODE = 0; /* sets pwm count top to be at 1 KHz and decode pwm in common mode*/ NRF_PWM0->COUNTERTOP = PWM_CLK / PWM_FREQUENCY; NRF_PWM0->DECODER = 0x00000002; NRF_PWM0->LOOP = 0; NRF_PWM0->SEQ[0].REFRESH = 0; NRF_PWM0->SEQ[0].ENDDELAY = 0; /* select clock source prescaler */ NRF_PWM0->PRESCALER = 0x00000001; /* enables the PWM */ NRF_PWM0->SEQ[0].PTR = ((uint32_t)nrf_pwm_sequence); NRF_PWM0->SEQ[0].CNT = sizeof(nrf_pwm_sequence) / sizeof(uint16_t); NRF_PWM0->ENABLE = 1; /* trigger it! */ NRF_PWM0->TASKS_SEQSTART[0] = 1; } /** * temp_pwm_set_val() * * @brief set the pwm with a new duty cicle * @param * @return */ static void temp_pwm_set_val(float required_energy) { #ifndef TEMP_CLOSED_LOOP /* saturate the energy expected */ if(required_energy < TEMP_MAINTENANCE_ENERGY) required_energy = TEMP_MAINTENANCE_ENERGY; if(required_energy > TEMP_MAXIMUM_ENERGY_AVAILABLE) required_energy = TEMP_MAXIMUM_ENERGY_AVAILABLE; #else /* saturate the energy required to the bound values, note in closed loop * we can increase the pwm output to the maximum during a cycle */ if(required_energy < TEMP_MAINTENANCE_ENERGY) required_energy = TEMP_MAINTENANCE_ENERGY; if(required_energy > TEMP_MAXIMUM_ENERGY_EXCURTION) required_energy = TEMP_MAXIMUM_ENERGY_EXCURTION; #endif /* obtains the duty cicle and sums it up with polarity offset */ uint16_t duty = (uint16_t)((required_energy / TEMP_MAXIMUM_ENERGY_EXCURTION) * (float)PWM_TOP_VALUE_FIX); duty |= PWM_POLARITY_OFFSET; /* update the duty cicle */ nrf_pwm_sequence[0] = duty; nrf_pwm_sequence[1] = duty; nrf_pwm_sequence[2] = duty; nrf_pwm_sequence[3] = duty; NRF_PWM0->TASKS_SEQSTART[0] = 1; } The nrf_pwm_sequence variable is a kind of PWM descriptor which holds the value of duty cycle concatenated with the polarity bit, the 4096 value means near 50% of duty cicle on channel 0, please note each pwm instance can be mapped to any pin of nordic chip and each instance has up to 4 channels. Please let me know if this was helpful. best Felipe 2018-02-08 7:50 GMT-02:00 Vikrant More <vikrant8051@...>:
--
Felipe S. Neves Embedded software & systems engineer Skype: fneves1989 +55 11 96610 – 0855 |
|