基于NRF52832实现SIF一线通收发数据处理

SIF协议

  • 一次传输一帧数据,传输结束后要求线路空闲状态为低电平,每次传输需一次性完整传输所有数据。

信号定义

  • Tosc定义: 250us

  • 同步信号
    基于NRF52832实现SIF一线通收发数据处理_第1张图片

  • 数据0信号:
    基于NRF52832实现SIF一线通收发数据处理_第2张图片

  • 数据1信号:
    基于NRF52832实现SIF一线通收发数据处理_第3张图片

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");
				}
				
				
			}
	}
	
	 
	
}

将发送和接收短接在一起,运行效果如下

基于NRF52832实现SIF一线通收发数据处理_第4张图片

你可能感兴趣的:(NRF52832个人学习笔记,嵌入式硬件,SIF一键通)