static uint32_t get_BitWidth(uint32_t baudrate)
{
uint32_t bit_width;
switch( baudrate )
{
case 4800:
bit_width = 0x7c; //123~152 for 4800, for nrf9160
break;
case 9600:
bit_width = 0x68; //104
break;
bit_width = 0x34; //52
break;
case 38400:
bit_width = 0x1a; //26
break;
case 57600:
bit_width = 0x11; //17
break;
case 115200:
bit_width = 0x9;
break;
default:
bit_width = ( 650000 / baudrate ) + 1; //for urf9160
break;
}
return bit_width;
}
void Soft_Uart_Send(char* data, uint32_t len)
{
k_mutex_lock(&s_softuarte_send_mutex, K_FOREVER);
char c;
uint32_t i,j;
for ( i = 0; i < len; i++ )
{
c = data[i];
// pull down as start bit
//GPIO_WRITE_LOW( gpio_port_tx, gpio_mask_tx );
nrf_gpio_pin_write(s_tx_pin, 0);
//delay_us(bit_width);
k_usleep(s_delay_width);
for ( j = 0; j < 8; j++ )
{
if ( c & 0x01 )
{
//GPIO_WRITE_HIGH( gpio_port_tx, gpio_mask_tx );
nrf_gpio_pin_write(s_tx_pin, 1);
}
else
{
//GPIO_WRITE_LOW( gpio_port_tx, gpio_mask_tx );
nrf_gpio_pin_write(s_tx_pin, 0);
}
//delay_us(bit_width);
k_usleep(s_delay_width+0x02); //0x02 for run mode
c >>= 1;
}
// pull high as stop bit
//GPIO_WRITE_HIGH( gpio_port_tx, gpio_mask_tx );
nrf_gpio_pin_write(s_tx_pin, 1);
//delay_us(bit_width);
k_usleep(s_delay_width);
if( data[i] == 0x0a )
{
c = 0x0d; //return
Soft_Uart_Send(&c, 1);
}
}
k_mutex_unlock(&s_softuarte_send_mutex);
}
void Soft_Uart_Recv(char* data, uint32_t len, uint32_t timeout)
{
k_mutex_lock(&s_softuarte_recv_mutex, K_FOREVER);
uint32_t i,j;
uint32_t c;
uint8_t b[8];
uint32_t input[1];
uint32_t starttime = k_uptime_get_32();
for ( i = 0; i < len; i++ )
{
c = 0;
memset(b, 0, sizeof(b));
// wait for start bit, first interrupt come in no wait
if( i > 0 )
{
while ( nrf_gpio_pin_read(s_rx_pin) > 0x0 )
{
if( k_uptime_get_32() - starttime >= timeout )
break;
}
k_usleep(s_delay_width/4);
}
for ( j = 0; j < 8; j++ )
{
k_usleep(s_delay_width);
b[j] = ( nrf_gpio_pin_read(s_rx_pin) ) ? 1 : 0;
}
for ( int j = 0; j < 8; j++ )
{
c |= (b[j] << j);
}
data[i] = c;
// wait for stop bit
while ( nrf_gpio_pin_read(s_rx_pin) == 0x0 )
{
if( k_uptime_get_32() - starttime >= timeout )
break;
}
}
k_mutex_unlock(&s_softuarte_recv_mutex);
}
void Init_SoftUart(uint32_t rx_pin, uint32_t tx_pin, uint32_t baudrate)
{
int err;
nrfx_gpiote_in_config_t in_config =
{
.sense = NRF_GPIOTE_POLARITY_HITOLO,
.pull = NRF_GPIO_PIN_PULLUP,
.is_watcher = false,
.hi_accuracy = true,
.skip_gpio_setup = true
};
nrfx_gpiote_out_config_t out_config =
{
.action = NRF_GPIOTE_POLARITY_TOGGLE,
.init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH,
.task_pin = false
};
s_rx_pin = rx_pin;
s_tx_pin = tx_pin;
IRQ_DIRECT_CONNECT(GPIOTE0_IRQn, 0, nrfx_gpiote_irq_handler, 0);
irq_enable(GPIOTE0_IRQn);
err = nrfx_gpiote_init(0);
if (err != NRFX_SUCCESS)
{
printk("nrfx_gpiote_init error: %08x", err);
return;
}
err = nrfx_gpiote_in_init(s_rx_pin, &in_config, rx_event_handler);
if (err != NRFX_SUCCESS)
{
printk("nrfx_gpiote_in_init error: %08x", err);
return;
}
if( out_config.task_pin == true )
{
err = nrfx_gpiote_out_init(s_tx_pin, &out_config);
if (err != NRFX_SUCCESS)
{
printk("nrfx_gpiote_out_init error: %08x", err);
return;
}
}
nrf_gpio_cfg(s_rx_pin,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
NRF_GPIO_PIN_PULLUP,
NRF_GPIO_PIN_H0H1,
NRF_GPIO_PIN_NOSENSE);
nrf_gpio_cfg(s_tx_pin,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_PULLUP,
NRF_GPIO_PIN_H0H1,
NRF_GPIO_PIN_NOSENSE);
nrfx_gpiote_in_event_enable(s_rx_pin, true);
if( out_config.task_pin == true )
{
nrfx_gpiote_out_task_enable(s_tx_pin);
}
s_delay_width = get_BitWidth(baudrate);
s_softuart_work = 1;
k_thread_create(&s_kthread_softuart, //local kthread_softuart will crash in k_sleep
stack_softuart,
THREAD_STACKSIZE,
SoftUart_Thread,
NULL,
NULL,
NULL,
-1,
K_INHERIT_PERMS,
K_NO_WAIT);
}
source download:
https://www.mediafire.com/file/gdzxlryiwbfnwdz/nrf9160_softuart.zip
沒有留言:
張貼留言