SENT信号捕获简介
在前面的文章中,我们学习了SENT的帧结构,这为我们的解析sent信号建立了一个基础,因为sent是一个高低差电平传输,所以,我们可以使用SENT的定时器触发中断来捕获sent的完整信号。
在汽车领域中,sent信号一般是传输压力和温度的,其中压力和温度各占三个sent帧,因此,传输的信号可以理解为以下结构:
| 对表基准 | 对比基准 | data | data | data | data | data | data | 检验 |
|---|
有了以上的消息结构,我们就能很快的进行数据解析
芯片我们采用STM32F4系列芯片,开发工具使用stm32cubemx、keil ARM、vscode。
首先我们的第一件事就是配置引脚等文件
如下图:
第一步先配置时钟



配置好时钟后,我们接下来开始配置TIM相关,在本文中使用高级定时器1的通道三作为输入捕获的io口。
选择中断方式,这里选择触发中断

在这块,我们把这个定时器的引脚改为高速模式

下面生成代码后可以开始写代码了。
在main.c中定义以下参数
static uint16_t captured_the_output_data[16] = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
static uint8_t capture_cnt_ch1 = 1; // 电平捕获次数通道1
#define SEND_TIME 10 // SENT发送的时间
static uint8_t Capture_times = 0;
typedef struct
{
volatile uint32_t high_val;
volatile uint32_t low_val;
float period_time; // 周期时刻
uint8_t contrast_time_base; // 对比时基
uint32_t data[32];
uint8_t capturd_number; // 捕获的数字
int read_val;
bool jedge; // 捕获是否完成标志位
} Capture_data;
Capture_data SENT_DATA_CH1 = {0};
之后编写中断函数值
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // TIM1CH1
{
static uint8_t val_buff_ch1 = 1; // 用来记录通道1装到那个数据了
switch (capture_cnt_ch1)
{
case 1:
__HAL_TIM_SetCounter(&htim3, 0); // 清空定时器3计数值
SENT_DATA_CH1.jedge = false;
memset(&SENT_DATA_CH1.data, 0, sizeof(SENT_DATA_CH1.data)); // 清空结构体的数组
SENT_DATA_CH1.high_val = __HAL_TIM_GetCounter(&htim3); // 获取第一个下降沿的时间
capture_cnt_ch1 = 2;
break;
case 2:
SENT_DATA_CH1.low_val = __HAL_TIM_GetCounter(&htim3); // 获取第二个下降沿的时间
SENT_DATA_CH1.period_time = (SENT_DATA_CH1.low_val - SENT_DATA_CH1.high_val) / 56; // 计算周期时刻
if (SENT_DATA_CH1.period_time >= (SEND_TIME * 0.8) || SENT_DATA_CH1.period_time <= (SEND_TIME * 1.2))
{
capture_cnt_ch1 = 3;
SENT_DATA_CH1.data[0] = SENT_DATA_CH1.low_val;
}
else
{
SENT_DATA_CH1.high_val = 0;
SENT_DATA_CH1.low_val = 0;
capture_cnt_ch1 = 1;
}
break;
case 3:
SENT_DATA_CH1.data[1] = __HAL_TIM_GetCounter(&htim3); // 获取第三个下降沿的时间
SENT_DATA_CH1.contrast_time_base = ((SENT_DATA_CH1.data[1] - SENT_DATA_CH1.data[0]) / SENT_DATA_CH1.period_time); // 计算对比度基准
capture_cnt_ch1 = 4;
break;
case 4:
val_buff_ch1 += 1;
SENT_DATA_CH1.data[val_buff_ch1] = __HAL_TIM_GetCounter(&htim3); // 获取下一个下降沿的时间
if (val_buff_ch1 >= 7)
{
capture_cnt_ch1 = 1;
SENT_DATA_CH1.jedge = true;
val_buff_ch1 = 1;
}
break;
}
}
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // 在中断模式下启动TIM1CH1输入捕获测量
}
下面我们还需要编写一个能够输出捕获到的数据的函数
void data_processing(void)
{
printf("Capture_times:%d\r\n",Capture_times);
if (SENT_DATA_CH1.jedge == true) // 如果通道1的标志位为真
{
printf("通道1周期时刻:%.2f\r\n", SENT_DATA_CH1.period_time); // 打印周期时刻
printf("通道1对比时基:%d\r\n", SENT_DATA_CH1.contrast_time_base); // 打印对比时基
for (int i = 0; i < 6; i++)
{
// 计算公式:(((后一个下降沿-前一个下降沿)/时刻)-对比时基)
SENT_DATA_CH1.capturd_number = (((SENT_DATA_CH1.data[i + 2] - SENT_DATA_CH1.data[i + 1]) / SENT_DATA_CH1.period_time) - SENT_DATA_CH1.contrast_time_base);
if (SENT_DATA_CH1.capturd_number >= 0 && SENT_DATA_CH1.capturd_number <= 15)
{
printf("通道1捕获的数字:");
printf("%d\r\n", captured_the_output_data[SENT_DATA_CH1.capturd_number]);
}
else
printf("通道1捕获失败\r\n"); // 打印捕获失败
}
SENT_DATA_CH1.jedge = false;
}
}
在main函数中,需要添加以下代码
HAL_TIM_Base_Start_IT(&htim1); // 开启定时器1
HAL_TIM_Base_Start_IT(&htim3); // 开启定时器3
定时器3需要自己去cubemx中配置,同定时器1一样,这里不做过多讲述
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // 在中断模式下启动TIM1CH1输入捕获测量
循环中调用
void data_processing(void)函数
在完成上述的代码编写与准备后,可以看到运行结果

这是一段连续的SENT信号,传输的数据是1,2,3,4,5,6
通过串口转发可以看到结果为

以上为本期的全部内容,求点赞求关注!!!!!
3001





