SIF协议
- 一次传输一帧数据,传输结束后要求线路空闲状态为低电平,每次传输需一次性完整传输所有数据。
信号定义
-
Tosc定义: 250us <Tosc<2ms,推荐值:500us
-
同步信号
-
数据0信号:
-
数据1信号:
SIF数据发送例程,这里Tosc使用(16+1)/32768*1000000=518uS
/**
* @brief 开启sense事件中断
*/
void BSP_gpiote_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_evt_handler_t pin_evt_handler,nrf_drv_gpiote_in_config_t *config)
{
NRF_LOG_INFO("charge_int_flag");
if (!nrf_drv_gpiote_is_init())
{
nrf_drv_gpiote_init();
}
nrf_drv_gpiote_in_config_t in_config={ \
.is_watcher = false, \
.hi_accuracy = true, \
.pull = NRF_GPIO_PIN_PULLUP, \
.sense = NRF_GPIOTE_POLARITY_TOGGLE, \
};
if(config == NULL)
{
config = &in_config;
}
nrf_drv_gpiote_in_init(pin, config, pin_evt_handler);
nrf_drv_gpiote_in_event_enable(pin, true);
}
/**
* @brief 关闭GPIOTE事件中断
*/
void disable_gpiote_evt_handler(nrfx_gpiote_pin_t pin)
{
NRF_LOG_INFO("disable_charge_handler");
nrf_drv_gpiote_in_event_disable(pin);
nrf_drv_gpiote_in_uninit(pin);
nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL);
}
/**
* @brieaf enable or disable gpio interrupt
*/
void gpiote_interrupt_switching(bool flag,nrfx_gpiote_pin_t pin)
{
if(flag)
nrf_drv_gpiote_in_event_enable(pin, true);
else
nrf_drv_gpiote_in_event_disable(pin);
}
#define SIF_TX_PIN 8
#define sif_low_level() nrf_gpio_pin_clear(SIF_TX_PIN)
#define sif_high_level() nrf_gpio_pin_set(SIF_TX_PIN)
APP_TIMER_DEF(m_sif_id);
#define TICK_SIF_INTERVAL 16
APP_TIMER_DEF(m_sif_1hz_id);
#define TICK_SIF_1HZ_INTERVAL 32767
uint8_t test_data[32] = {0x12,0x34,0x56,0x78};
typedef struct
{
uint8_t *pData;
uint8_t len;
uint8_t state;
uint8_t pos;
uint8_t mask_data;
uint32_t hi_tosc;
uint32_t lo_tosc;
}SIF_SEND_DATA_T;
typedef enum
{
END_SEND,
DATA_HEADER,
DATA_SEND,
}E_SEND_DATA_STATE;
SIF_SEND_DATA_T g_send_data;
void sif_send_handler(void);
static void timer_sif_timeout_handler(void * p_context)
{
UNUSED_PARAMETER(p_context);
if(g_send_data.state != END_SEND)
{
sif_send_handler();
}
}
void send_data_ready(uint8_t *dat,uint8_t len)
{
g_send_data.pData = dat;
g_send_data.len = len;
g_send_data.state = DATA_SEND;
g_send_data.lo_tosc = SYNC_LOW_TOSC;
g_send_data.hi_tosc = SYNC_HIGH_TOSC;
g_send_data.pos = 8;
g_send_data.mask_data = 0x80;
}
void sif_send_handler(void)
{
if(g_send_data.lo_tosc)
{
sif_low_level();
g_send_data.lo_tosc--;
}
else if(g_send_data.hi_tosc)
{
sif_high_level();
g_send_data.hi_tosc--;
}
else
{
sif_low_level();
if(g_send_data.pos--)
{
// NRF_LOG_INFO("pData %X len %d pos %d %d",g_send_data.pData[0],g_send_data.len,g_send_data.pos,g_send_data.pData[0] & g_send_data.mask_data ? 1:0);
if(g_send_data.pData[0] & g_send_data.mask_data)
{
g_send_data.lo_tosc = ONE_TOSC;
g_send_data.hi_tosc = TWO_TOSC;
}
else
{
g_send_data.hi_tosc = ONE_TOSC;
g_send_data.lo_tosc = TWO_TOSC;
}
g_send_data.mask_data >>= 1;
g_send_data.lo_tosc--;
}
else
{
// NRF_LOG_INFO("pData %X len %d",g_send_data.pData[0],g_send_data.len);
if(--g_send_data.len == 0)
{
g_send_data.state = END_SEND;
}
else
{
g_send_data.pData++;
g_send_data.pos = 8;
g_send_data.mask_data = 0x80;
}
}
}
}
static void sif_1hz_handler(void * p_context)
{
UNUSED_PARAMETER(p_context);
send_data_ready(test_data,SIF_DATA_LEN);
}
void sif_init(void)
{
BSP_gpiote_init(SIF_RX_PIN,sif_int_handler,NULL);
nrf_gpio_cfg_output(SIF_TX_PIN);
uint32_t err_code = app_timer_create(&m_sif_id,
APP_TIMER_MODE_REPEATED,
timer_sif_timeout_handler);
APP_ERROR_CHECK(err_code);
app_timer_start(m_sif_id,TICK_SIF_INTERVAL,NULL);
err_code = app_timer_create(&m_sif_1hz_id,
APP_TIMER_MODE_REPEATED,
sif_1hz_handler);
APP_ERROR_CHECK(err_code);
app_timer_start(m_sif_1hz_id,TICK_SIF_1HZ_INTERVAL,NULL);
}
SIF接收例程
#include "app_timer.h"
#define SIF_RX_PIN 9
#define ONE_TOSC 1
#define TWO_TOSC (ONE_TOSC*2)
#define SYNC_LOW_TOSC (ONE_TOSC*32)
#define SYNC_HIGH_TOSC (ONE_TOSC*1)
#define SIF_DATA_LEN 4
typedef struct
{
uint8_t recv_buf[32];
uint8_t len;
uint8_t pos;
uint8_t state;
uint32_t tsoc_cal;
uint32_t sync_tsoc;
}SIF_RECV_DATA_T;
typedef enum
{
END_RECV,
RECV_HEADER,
DATA_RECV,
}E_RECV_DATA_STATE;
SIF_RECV_DATA_T g_sif_recv_data;
void sif_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
static uint32_t low_time;
static uint32_t high_time;
static uint32_t pre_tick;
uint32_t cur_tick = app_timer_cnt_get();
uint32_t diff = cur_tick >= pre_tick ? cur_tick-pre_tick : ((uint32_t)-1)-cur_tick+pre_tick;
pre_tick = cur_tick;
// NRF_LOG_INFO("diff %d",diff);
if(nrf_gpio_pin_read(pin)) // hi
{
if(g_sif_recv_data.state == END_RECV)
{
g_sif_recv_data.sync_tsoc = diff;
g_sif_recv_data.state = RECV_HEADER;
}
else if(g_sif_recv_data.state == DATA_RECV)
{
low_time = diff;
}
}
else
{
if(g_sif_recv_data.state == RECV_HEADER)
{
g_sif_recv_data.tsoc_cal = diff;
if(g_sif_recv_data.sync_tsoc > g_sif_recv_data.tsoc_cal * 4)
{
g_sif_recv_data.sync_tsoc = 0;
g_sif_recv_data.state = DATA_RECV;
g_sif_recv_data.len = 0;
g_sif_recv_data.pos = 8;
memset(g_sif_recv_data.recv_buf,0,sizeof(g_sif_recv_data.recv_buf));
}
else
{
g_sif_recv_data.state = END_RECV;
}
}
else if(g_sif_recv_data.state == DATA_RECV)
{
uint8_t level;
uint32_t max_diff,min_diff;
if(low_time > diff) // low
{
level = 0;
max_diff = low_time;
min_diff = diff;
}
else
{
level = 1;
max_diff = diff;
min_diff = low_time;
}
if((max_diff > g_sif_recv_data.tsoc_cal *7/5) && (min_diff > g_sif_recv_data.tsoc_cal *7/10 ))
{
g_sif_recv_data.recv_buf[g_sif_recv_data.len] <<= 1;
g_sif_recv_data.recv_buf[g_sif_recv_data.len] |= level;
if(--g_sif_recv_data.pos == 0)
{
g_sif_recv_data.pos = 8;
NRF_LOG_INFO("SIF RECV %x",g_sif_recv_data.recv_buf[g_sif_recv_data.len]);
if(++g_sif_recv_data.len >= SIF_DATA_LEN)
{
g_sif_recv_data.len = 0;
g_sif_recv_data.state = END_RECV;
NRF_LOG_INFO("============================================");
}
}
}
else
{
g_sif_recv_data.state = END_RECV; // 出错
NRF_LOG_INFO("SIF RECV ERR");
}
}
}
}