The SIF() function was initially added and not tested.
This commit is contained in:
parent
ebb058989d
commit
386bbe06ee
227
Source/SIF.c
227
Source/SIF.c
@ -2,8 +2,235 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define DATA_REV_PIN gpio_get(SIF_REV_PIN)
|
||||
|
||||
#ifdef _SIF_DEBUG_
|
||||
char log_str[128] = { 0 };
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
INITIAL_STATE = 0, // 初始状态,等待接收同步信号
|
||||
SYNC_L_STATE = 1, // 接收同步低电平信号状态
|
||||
SYNC_H_STATE = 2, // 接收同步高电平信号状态
|
||||
DATA_REV_STATE = 3, // 读取数据码电平状态
|
||||
END_SIGNAL_STATE = 4, // 接收结束电平信号状态
|
||||
RESTART_REV_STATE = 5 // 接收过程出错重新接收状态
|
||||
} REV_STATE_e; // 接收数据状态枚举
|
||||
|
||||
unsigned char receive_state = 0; //接收数据状态
|
||||
unsigned char receive_bit_num = 0; //接收的bit位个数
|
||||
unsigned char receive_data_num = 0; //接收的数据个数
|
||||
|
||||
unsigned char sif_receive_data_buf[REV_DATA_NUM] = { 0 }; //接收数据缓存数组如果一帧数据有多个数据打开注释
|
||||
unsigned char sif_receive_data[REV_DATA_NUM] = { 0 };
|
||||
unsigned int H_L_Level_time_cnt = 0; //高低电平时间计数
|
||||
|
||||
unsigned int Tosc = TOSC; //波形时基单元,一般带波特率自适应的,不会说明高低电平的时间,会用一个Tosc时基描述
|
||||
//如上面的波形图,要求 32Tosc = 0.5ms = 500us
|
||||
//所以:一个Tosc = 500us/32 ≈ 15us,而定时器0单次定时时间为5us,所以实际一个Tosc = 15us/5us = 3 次
|
||||
//可以理解为 5us 是人为设置的一个定时器单次定时时间,再这个定时时间的基础上又产生了一个实际时基Tosc,用在波形上,波形基于这个Tosc时基单元
|
||||
//可以动态的调整高低电平的时间,只要Tosc改变,992Tosc和32Tosc以及64Tosc对应的时间也会随之改变;然后我们反过来思考,再不知道波特率的情况下,
|
||||
//去读取同步信号高电平的时间,将读到的时间计数H_L_Level_time_cnt * 15us是高电平的真实维持时间 = 32 * Tosc * 5us = SHORT_TIME_NUM * Tosc * 5us
|
||||
//Tosc = H_L_Level_time_cnt / SHORT_TIME_NUM
|
||||
//在本案例中,一帧数据 = 992Tosc+32Tosc+(64+32)*8*12Tosc = 10240*Tosc 次
|
||||
//1秒钟 = 1000000us,单次定时 5us,则1s / 5us = 200000 次
|
||||
//则1秒钟可以接收 200000 / (10240 * Tosc) = 200000/10240/Tosc = 19/Tosc 帧数据
|
||||
|
||||
uint8_t start_H_L_Level_timming_flag = 0; //开始高低电平计时标记
|
||||
uint8_t has_read_bit = 0; //1-已经读取一个bit位
|
||||
uint8_t read_success = 0; //一帧数据是否读取成功,0-不成功,1-成功
|
||||
uint8_t is_end_bit = 0; // 结束帧判定 0-未结束,1-结束标志
|
||||
|
||||
|
||||
void GPIO_SIF_Init(void)
|
||||
{
|
||||
gpio_init(SIF_REV_PIN);
|
||||
gpio_set_dir(SIF_REV_PIN, GPIO_OUT);
|
||||
}
|
||||
|
||||
void TIMER_SIF_IRQHandler(void)
|
||||
{
|
||||
if (start_H_L_Level_timming_flag == 1) {
|
||||
H_L_Level_time_cnt++; //高低电平维持时间计数变量
|
||||
}
|
||||
|
||||
Receive_SIF_Data_Handle(); //接收数据处理,波特率自适应
|
||||
|
||||
}
|
||||
|
||||
void Receive_SIF_Data_Handle(void)
|
||||
{
|
||||
switch (receive_state) //检测当前接收数据状态
|
||||
{
|
||||
case INITIAL_STATE: //初始状态,未接收到同步信息,进行同步判断
|
||||
if (DATA_REV_PIN == LOW) //判断接收引脚的电平状态,当读到低电平时,开始计时
|
||||
{
|
||||
receive_bit_num = REV_BIT_NUM; //重置bit位计数器
|
||||
receive_data_num = 0; //重置接收数据个数
|
||||
H_L_Level_time_cnt = 0; //高低电平计时变量清0
|
||||
read_success = 0; //结束位置低电平判定清零
|
||||
start_H_L_Level_timming_flag = 1; //开始高低电平计时
|
||||
is_end_bit = 0;
|
||||
receive_state = SYNC_L_STATE; //进入读取同步低电平信号状态
|
||||
memset(sif_receive_data_buf, 0, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
case SYNC_L_STATE: //在读取同步低电平信号期间
|
||||
if (H_L_Level_time_cnt > SYNC_TIME_NUM * Tosc) //如果低电平时间 > SYNC_TIME_NUM*Tosc=992*3*5us
|
||||
{ //同步状态空闲时间大于15ms
|
||||
if (DATA_REV_PIN == HIGH) //判断接收引脚的电平状态,当读到高电平时
|
||||
{
|
||||
H_L_Level_time_cnt = 0; //高低电平计时变量清0
|
||||
receive_state = SYNC_H_STATE; //进入读取同步信号高电平状态
|
||||
}
|
||||
} else {
|
||||
if (DATA_REV_PIN == HIGH) //同步信号低电平检测期间读到高电平重新计时
|
||||
{
|
||||
receive_state = RESTART_REV_STATE; //进入重新接收状态
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SYNC_H_STATE: //在读取同步高电平信号期间
|
||||
if (H_L_Level_time_cnt >= LOGIC_CYCLE_NUM * Tosc) //如果高电平时间超过了(32+64=96)个Tosc,则认为超时
|
||||
{
|
||||
receive_state = RESTART_REV_STATE; //进入重新接收状态
|
||||
} else {
|
||||
if (DATA_REV_PIN == LOW) //同步信号高电平检测期间读到低电平
|
||||
{
|
||||
//在同步信号高电平检测期间读到低电平可能有如下状态:
|
||||
//1、高电平时间短,不满32Tosc
|
||||
//2、高电平时间正好=32Tosc
|
||||
//3、高电平时间长,超过32Tosc
|
||||
//不管何种状态,都要 调整 Tosc 的值达到波特率自适应
|
||||
//H_L_Level_time_cnt * 5us 要求是 SHORT_TIME_NUM * Tosc * 5us,
|
||||
//即 H_L_Level_time_cnt = SHORT_TIME_NUM * Tosc
|
||||
Tosc = H_L_Level_time_cnt / SHORT_TIME_NUM; //调整 Tosc 的值
|
||||
H_L_Level_time_cnt = 0; //高低电平计时变量清0
|
||||
receive_state = DATA_REV_STATE; //进入读取数据码低电平状态
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_REV_STATE: //在读取数据码电平期间
|
||||
//逻辑"0"为 64Tosc低电平 + 32Tosc高电平
|
||||
//逻辑"1"为 32Tosc低电平 + 64Tosc高电平
|
||||
//不管是逻辑"0"还是逻辑"1",周期一样,都是32Tosc + 64Tosc = 96Tosc
|
||||
//可以取中间时间点进行判断,96Tosc / 2 = 48Tosc,当计数>=48Tosc时读取引脚电平
|
||||
//如果还没有读取一个bit位,且时间计数已经>=48Tosc
|
||||
if ((has_read_bit == 0) && (H_L_Level_time_cnt >= (HALF_LOGIC_CYCLE * Tosc))) {
|
||||
sif_receive_data_buf[receive_data_num] |= DATA_REV_PIN;
|
||||
has_read_bit = 1;
|
||||
}
|
||||
//如果已经读取一个bit位,且时间计数已经>=96Tosc,说明一个逻辑周期过去了
|
||||
if ((has_read_bit == 1) && (H_L_Level_time_cnt >= (LOGIC_CYCLE_NUM * Tosc))) {
|
||||
H_L_Level_time_cnt = 0; //高低电平计时变量清0
|
||||
has_read_bit = 0; //清0,读取下一个bit位
|
||||
receive_bit_num--; //接收的bit数--
|
||||
if (receive_bit_num == 0) //如果一个字节8个bit位接收完成
|
||||
{
|
||||
receive_data_num++; //接收的数据个数++
|
||||
receive_bit_num = REV_BIT_NUM; //重置接收bit位个数
|
||||
|
||||
if (receive_data_num >= REV_DATA_NUM) //如果数据采集完毕 超出了最大值
|
||||
{
|
||||
start_H_L_Level_timming_flag = 0; //停止高低电平计时
|
||||
H_L_Level_time_cnt = 0; //定时器计数值清0
|
||||
receive_state = INITIAL_STATE; //接收状态清0
|
||||
}
|
||||
} else //如果一个字节8个bit位还没有接收完成
|
||||
{
|
||||
//将接收数据缓存左移一位,数据从高bit位开始接收
|
||||
sif_receive_data_buf[receive_data_num] = sif_receive_data_buf[receive_data_num] << 1;
|
||||
|
||||
}
|
||||
}
|
||||
// 记录 结束标志
|
||||
if (H_L_Level_time_cnt == (END_SIGNAL_FLAG_NUM * Tosc) && (DATA_REV_PIN == LOW)) {
|
||||
is_end_bit = 1;
|
||||
has_read_bit = 0;
|
||||
read_success = 1; //一帧数据读取成功
|
||||
#ifdef _SIF_DEBUG_
|
||||
sprintf(log_str, "rn:%d,%s.", receive_data_num, sif_receive_data_buf);
|
||||
#endif
|
||||
Check_Sum_Handle();
|
||||
start_H_L_Level_timming_flag = 0; //停止高低电平计时
|
||||
H_L_Level_time_cnt = 0; //定时器计数值清0
|
||||
receive_state = INITIAL_STATE; //接收状态清0
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case END_SIGNAL_STATE: //在接收结束信号低电平期间
|
||||
if (DATA_REV_PIN == LOW) {
|
||||
if (H_L_Level_time_cnt >= END_SIGNAL_TIME_NUM * Tosc) //如果读到低电平时间>=5ms
|
||||
{
|
||||
read_success = 1; //一帧数据读取成功
|
||||
Check_Sum_Handle();
|
||||
start_H_L_Level_timming_flag = 0; //停止高低电平计时
|
||||
H_L_Level_time_cnt = 0; //定时器计数值清0
|
||||
receive_state = INITIAL_STATE; //接收状态清0
|
||||
}
|
||||
} else //结束信号低电平检测期间一直为低
|
||||
{
|
||||
//if (H_L_Level_time_cnt >= SYNC_L_TIME_NUM) //如果读到低电平时间>=10ms,认为超时
|
||||
{ //一帧数据发送完成后需要间隔50ms才发送第二帧数据,期间肯定会被拉高
|
||||
receive_state = RESTART_REV_STATE; //进入重新接收状态
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESTART_REV_STATE: //重新接收数据状态
|
||||
start_H_L_Level_timming_flag = 0; //停止高低电平计时
|
||||
H_L_Level_time_cnt = 0; //定时器计数值清0
|
||||
is_end_bit = 0;
|
||||
receive_state = INITIAL_STATE; //接收状态清0
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *pGetSIFData(void) //获取SIF数据
|
||||
{
|
||||
return sif_receive_data;
|
||||
}
|
||||
|
||||
#ifdef _SIF_DEBUG_
|
||||
char *pGetLogStr(void) //获取SIF数据
|
||||
{
|
||||
return log_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Check_Sum_Handle()
|
||||
{
|
||||
if (read_success == 1) //如果成功读取一帧数据
|
||||
{
|
||||
//一帧数据接收成功后先根据协议要求进行校验和,验证数据的正确性
|
||||
//如果数据正确,根据接收的数据进行分析获取需要的内容
|
||||
//if (check_OK)
|
||||
{
|
||||
memset(sif_receive_data, 0, REV_DATA_NUM);
|
||||
memcpy(sif_receive_data, sif_receive_data_buf, REV_DATA_NUM);
|
||||
memset(sif_receive_data_buf, 0, REV_DATA_NUM);
|
||||
}
|
||||
|
||||
read_success = 0; //读取一帧数据清0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SIF(void *p)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
GPIO_SIF_Init();
|
||||
while (1)
|
||||
{
|
||||
char *SIF_DATA = (char *)pGetSIFData();
|
||||
|
||||
printf("%s", SIF_DATA);
|
||||
vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
32
Source/SIF.h
32
Source/SIF.h
@ -7,6 +7,38 @@
|
||||
#include "semphr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define _SIF_DEBUG_ 1
|
||||
|
||||
#define LOW 0 //低电平
|
||||
#define HIGH 1 //高电平
|
||||
#define SYNC_TIME_NUM 992 //992Tosc中的992
|
||||
#define SHORT_TIME_NUM 32 //一个逻辑周期中短的时间:32Tosc中的32
|
||||
#define LONG_TIME_NUM 64 //一个逻辑周期中长的时间:64Tosc中的64
|
||||
#define LOGIC_CYCLE_NUM 96 //一个逻辑周期 SHORT_TIME_NUM + LONG_TIME_NUM
|
||||
#define HALF_LOGIC_CYCLE 48 //一个逻辑周期的1/2,即 LOGIC_CYCLE_NUM/2
|
||||
#define END_SIGNAL_FLAG_NUM 80 // 判断80左右的位置是否为低电平,如果为低电平 则
|
||||
#define END_SIGNAL_TIME_NUM 100 //结束信号电平时间:5ms低电平 + Nms高电平,实际检测5ms低电平就行,一帧数据发送完成后检测5ms低电平就代表完成了,不发数据的时候上拉电阻拉高了
|
||||
#define REV_BIT_NUM 8 //接收的bit位个数,看是按字节接收还是按字接收,1字节=8bit,1字=2字节=16bit
|
||||
#define REV_DATA_NUM 16 //接收的数据个数
|
||||
|
||||
#define SIF_REV_PIN 13 // 定义sif通信的引脚
|
||||
#define TOSC 3 // 定义系统TOSC基数倍数,默认定义为3,程序中支持自适应了
|
||||
|
||||
|
||||
|
||||
void GPIO_SIF_Init(void); // GPIO初始化函数
|
||||
void Timer_SIF_Init(void); //定时器SIF初始化函数
|
||||
void TIMER_SIF_IRQHandler(void); // 定时器中断回调函数
|
||||
void Receive_SIF_Data_Handle(void); //接收数据处理—带校准位,即波特率自适应
|
||||
void Check_Sum_Handle(void); // 校验和处理
|
||||
unsigned char *pGetSIFData(void); //获取SIF数据
|
||||
|
||||
#ifdef _SIF_DEBUG_
|
||||
char *pGetLogStr(void); //获取日志字符串
|
||||
#endif
|
||||
|
||||
|
||||
extern void SIF(void *p);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "EC800M_GPS.h"
|
||||
#include "EC800M_4G.h"
|
||||
#include "HC-04.h"
|
||||
#include "SIF.h"
|
||||
|
||||
void Led_Blinky(void *pvParameters)
|
||||
{
|
||||
@ -76,6 +77,8 @@ int main(void)
|
||||
TaskHandle_t EC800M_4G_xHandle = NULL;
|
||||
TaskHandle_t PN532_xHandle = NULL;
|
||||
TaskHandle_t HC_04_xHandle = NULL;
|
||||
|
||||
TaskHandle_t SIF_xHandle = NULL;
|
||||
|
||||
// 板载LED闪烁
|
||||
xReturned = xTaskCreate(Led_Blinky, "Blinky task", 512, NULL, tskIDLE_PRIORITY, &Led_Blinky_xHandle);
|
||||
@ -118,6 +121,13 @@ int main(void)
|
||||
{
|
||||
printf("HC-04 Task Error!");
|
||||
}
|
||||
|
||||
// SIF 模块
|
||||
xReturned = xTaskCreate(SIF, "SIF task", 512, NULL, tskIDLE_PRIORITY, &SIF_xHandle);
|
||||
if (xReturned == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
|
||||
{
|
||||
printf("HC-04 Task Error!");
|
||||
}
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user