EBIKE-FreeRTOS/Source/SIF.c
2024-04-16 17:56:53 +08:00

222 lines
9.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SIF.h"
#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时基描述
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
gpio_init(SIF_REV_PIN);
// 将 GPIO 设置为输入模式
gpio_set_dir(SIF_REV_PIN, GPIO_IN);
// 启用下拉模式
gpio_pull_down(SIF_REV_PIN);
}
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) // 同步信号高电平检测期间读到低电平
{
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: // 在读取数据码电平期间
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 ;
}