- 打卡等级:初来乍到
- 打卡总天数:8
- 最近打卡:2026-04-08 16:14:47
已绑定手机
注册会员
- 积分
- 67
|
这两天一直在调,没办法正确捕捉到脉冲宽度, STC32G8K48单片机, P3.7作为脉宽信号输入 (J1850_VPW), 起始信号实测为200us, 代码每次运行到 检测小于最小值163us报错返回。u16 j1850_vpw_recv_msg(uint8_t *msg_buf, 通过定时器0 1T模式下 运行(初值设为0)、停止来计时。 P37高阻输入。
u16 get_timer0(void)
{
return (((u16)(TH0)<<8 )|TL0);
}
u16 j1850_vpw_recv_msg(uint8_t *msg_buf, u8 checkLength)
{
uint8_t nbits; // 字节内的比特位置计数器
uint8_t nbytes; // 接收到的字节数
uint8_t bit_state;// 用于比较比特状态,激活或被动
uint16_t tcnt1_buf;
/*
等待响应
*/
// EA = 0;
timer0_start();
while(0==VPW_IN) // 只要总线是被动的(空闲)就运行
{
if(get_timer0() >= WAIT_100us) // 检查 100us
{
TR0 = 0;
return J1850_RETURN_CODE_NO_DATA | 0x80; // 错误,100us 内无响应
}
}
// TR0 = 0;
// 等待 SOF
timer0_start(); // 重启 timer0
while(1==VPW_IN) // 只要总线是激活的(SOF 是一个激活符号)就运行
{
if(get_timer0() >= RX_SOF_MAX) {
TR0 = 0;
return J1850_RETURN_CODE_BUS_ERROR | 0x80
; // SOF 超时错误
}
}
// TR0 = 0;
if(get_timer0() < RX_SOF_MIN) {
printf("TCNT = %u \r\n",get_timer0());
TR0 = 0;
return J1850_RETURN_CODE_BUS_ERROR | 0x80; // 错误,符号不是 SOF
}
bit_state = VPW_IN; // 存储实际总线状态
timer0_start();
for(nbytes = 0; nbytes < checkLength ? 12 : RX_BUFFER_MAX_LEN; ++nbytes)
{
nbits = 8;
do
{
*msg_buf <<= 1;
while(VPW_IN == bit_state) // 比较上一个和实际总线状态,等待变化
{
if(TCNT1 >= RX_EOD_MIN ) // 检查 EOD 符号
{
TR0 = 0;
return nbytes; // 返回接收到的字节数
}
}
bit_state = VPW_IN; // 存储实际总线状态
tcnt1_buf = TCNT1;
timer0_start();
if( tcnt1_buf < RX_SHORT_MIN) return J1850_RETURN_CODE_BUS_ERROR | 0x80; // 错误,脉冲过短
// 检查短激活脉冲 = "1" 比特
if( (tcnt1_buf < RX_SHORT_MAX) && !VPW_IN )
*msg_buf |= 1;
// 检查长被动脉冲 = "1" 比特
if( (tcnt1_buf > RX_LONG_MIN) && (tcnt1_buf < RX_LONG_MAX) && VPW_IN )
*msg_buf |= 1;
} while(--nbits);// 结束 8 比特 while 循环
++msg_buf; // 存储下一个字节
} // 结束 12 字节 for 循环
// 在最多 12 个字节后返回
TR0 = 0;
// EA = 1;
return nbytes;
}
|
|