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.