Hello everyone,
I write this post because I haven't been able to find a solution to a problem I'm having to implement a parallel to serial converter. I am employing the nrf52 DK device.
My scheme of the circuit is the following one:
- Inputs : -Clock : 2 MHz signal.
-Flag : 150 KHz signal.
- Outputs : - Out : Serial output.
- Enable: Signal that in HIGH while Out is being transmitted.
-Internal: - Values_8 : Array of 8 bool elements (they can change).
- What do I want to do? : Every time Flag goes low to high, I have to transmit Values_8 by Out at Clock frequency. It means, each of the 8 elements of Values_8 have to be transmitted in a Clock period.
Firstly, I am trying to transmit the information 1 bit at 2 MHz in a serial way, without Flag. However, my main problem relies on the operation frequency: I set the input pin Clock as a GPIOTE with high priority, sensing a rising edge of this pin. When the edge is sensed, it employs its event_handler where a GPIO output is set or clear regarding the value of Value_8. However, this works only for a frequency of 100 kHz. I attach a simpler code which toggle a pin when Clock goes low to high. It only works for frequencies below 100 kHz. The event is "in_pin_handler".
void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { nrf_gpio_pin_toggle(28); } /** * @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output, * and configures GPIOTE to give an interrupt on pin change. */ static void gpio_init(void) { NRF_CLOCK->TASKS_HFCLKSTART = 1; nrf_drv_gpiote_init(); nrf_gpio_cfg_output(28); nrf_gpio_cfg_sense_input(22, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true); in_config.pull = NRF_GPIO_PIN_NOPULL; nrf_drv_gpiote_in_init(22, &in_config, in_pin_handler); nrf_drv_gpiote_in_event_enable(22, true); } /** * @brief Function for application main entry. */ int main(void) { gpio_init(); while (true) { // Do nothing. } } /** @} */
If I implement this employing GPIOTEs connection by PPI (This is the code) it correctly works at 2 MHz, however I don't know how to transmit the information of a bit to the output, I only can set, clear or toggle the output pin. I don't know how to implement an if statement, or something like that, in order to check the value (high or low) of the output pin.
static void led_blinking_setup() { uint32_t compare_evt_addr; uint32_t gpiote_task_addr; nrf_ppi_channel_t ppi_channel; ret_code_t err_code; nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); //this has be configured regarding the value of a global variable err_code = nrf_drv_gpiote_out_init(28, &config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_ppi_channel_alloc(&ppi_channel); APP_ERROR_CHECK(err_code); nrf_gpio_cfg_sense_input(22, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true); in_config.pull = NRF_GPIO_PIN_NOPULL; nrf_drv_gpiote_in_init(22, &in_config, NULL); nrf_drv_gpiote_in_event_enable(22, true); compare_evt_addr = nrf_drv_gpiote_in_event_addr_get(22); gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(28); err_code = nrf_drv_ppi_channel_assign(ppi_channel, compare_evt_addr, gpiote_task_addr); APP_ERROR_CHECK(err_code); err_code = nrf_drv_ppi_channel_enable(ppi_channel); APP_ERROR_CHECK(err_code); nrf_drv_gpiote_out_task_enable(28); } int main(void) { NRF_CLOCK->TASKS_HFCLKSTART = 1; ret_code_t err_code; err_code = nrf_drv_ppi_init(); APP_ERROR_CHECK(err_code); err_code = nrf_drv_gpiote_init(); APP_ERROR_CHECK(err_code); led_blinking_setup(); while (true) { __WFI(); // Do Nothing - GPIO can be toggled without software intervention. } }
I would like to know a possible solution to achieve, or an event_handler at upper frequencies, or an alternative to set/clear a GPIO pin at high frequencies driven by an external Clock and regarding a global variable (or memory) that is changing.
Thank you so much for your help.