问题如题,原本是使用计时器输入捕获功能获取脉冲数的问题,后将代码修改如下使其仅仅只是计数输出一下0至10000的数字:
int main(void)
{
u16 i = 0, j;
LED_Init(); //LED端口初始化
uart_init(115200);
printf("%d\r\n", 70000); //串口输出程序启动标志
while(1)
{
printf("%d\r\n", i++);
if(i >= 10000) break;
}
LED0 = 0;
printf("%d, %d\r\n", i, j);
}
在上位机中根据输出数字显示波形,其波形如下:

在跳出while循环后其会跳转至循环前继续执行两次,最终在第三次正常结束。
本人才疏学浅,初次遇到这种情况,真诚求助orz!
以下为原问题,目前来看可以暂时排除计时器的原因。
问题如题,电机的AB相分别连接TIM3的通道1和通道2,主函数代码如下:
/************************************************
通过输入捕获获取有刷直流电机的脉冲数
************************************************/
int main(void)
{
u16 i = 0, j;
LED_Init();
uart_init(115200);
TIM3_Encoder_Init(65535, 0);
printf("%d, %d\r\n", 70000, 0); //串口输出程序启动标志
while(i < 10000) //i为累计检测到的脉冲数,如果累计检测到了10000个脉冲就结束循环
{
j = getEncoder(); //getEncoder()返回本次循环的脉冲数,返回后会将CNT置零
printf("%d, %d\r\n", i, j); //向串口1输出 累计的脉冲数 和 本次循环获取的脉冲数
if(j < 100) i += j; //排除可能存在的错误值后将脉冲数累计
}
LED0 = 0;
printf("%d, %d\r\n", i, j);
}
同时使用上位机观察串口输出的波形,理论上输出累积至10000以上就会结束,可实际输出波形如下:

经多次测试,在累计脉冲数第一次和第二次接近循环判断值时程序会重启并重新计数,至第三次才会正常的结束这个计数过程。
输入捕获部分代码如下:
//arr:自动重装值,测试中使用65535
//psc:时钟预分频数,测试中使用0
void TIM3_Encoder_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_6 | GPIO_Pin_7);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0x0A;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM3, ENABLE);
}
//获取当前脉冲数,获取后置0
u16 getEncoder()
{
u16 temp;
temp = TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0);
return temp;
}
本人纯纯清澈愚蠢大学生一枚,真诚求助orz!
兄弟啊,你这while循环要死循环才行啊,要不然都不知道运行到哪里去了。
呵呵还真是没见while(1)
找个简单的ST例程跑跑,看看到底是硬件方面还是软件方面的原因。
顺便提醒下,编码器的计数方向即向上计数还是向下计数,是由你的TI1 TI2输入波形的相对时序决定的。
这里有个关于STM32定时器编码器应用演示你可以参考下。基于编码器信号的PWM输出示例
但从你具体描述来看,好像是在说计数器重启了,这跟系统重启是两码事。
计数器溢出发生重装是正常的。
你主循环里对计数个数进行累计,在通过getEncoder()函数获取计数值
时,并对TIM3的counter清0,又重新开始计数。
如果说你那个while判断循环体执行时间肯定不会超过oxffff个计数脉冲所对应的时间的话,
除了第一个初始读数值外,其它时候读到的数据应该是基本一样的,因为你每次读后都清零了。
如果说那个while判断循环体执行时间有可能超过oxffff个计数脉冲所对应的时间的话,那每次
读到的数据就是波动的,如果不考虑了溢出,计数偏差可能比较大,要看具体情况。
不太清楚你具体的应用目的,你在每次测试前在那个while判断循环之前加一句TIM_SetCounter(TIM3, 0);会怎样?
感谢大佬的回复orz。
关于重启的情况,是因为我在每次进入循环获取脉冲数之前会先向串口输出一个很高的数据使其在波形图中形成一个峰值来表示开始获取脉冲,这个串口输出在进入循环之前:
printf("%d, %d\r\n", 70000, 0); //串口输出程序启动标志
,本人也是初识嵌入式开发以我浅薄的认识来看似乎只有按下RESET键重新执行程序才可能再次输出这个数据,如果表述不清导致误解请原谅orz。关于while判断循环体执行时间的情况,依我所见的话是不会超出oxffff个计数脉冲所对应的时间的,如您所说每次读取的数据也是几乎一样的,如主题附图中绿线所示,波动范围很小,之所以存在波动范围是因为尚未添加电机的驱动,每次测试都是手拧(毕竟只是为了数脉冲数)。
这个程序的目的是仅仅是为了测试有刷直流电机的使用,通过判断编码器发出的脉冲数量来控制电机的圈数,可是在判断编码器脉冲数量这一步就出现解决不了的问题了orz。
大佬的建议我尝试了一下,并没有发生什么变化orz。
不过还是感谢大佬的留言,期待您更多的回复。
大佬我发现了一个恐怖的情况啊,我在main中把计时器相关的部分删掉后仅仅只是向串口输出数字结果还是有重复执行的bug啊orz,原问题已修改您看这个还能解决吗。
感谢大佬的回复,经测试无论是什么项目只要main函数执行完毕系统就会自动重启,重启次数各个项目并不相同。
本人初次接触嵌入式开发,目前暂不确定这个现象到底是硬件的问题还是STM32F1的机制,暂时通过在main函数的结尾增加死循环来确保系统不会重启,具体的情况我接下来会与正点原子的客服进行沟通尝试搞清楚。
感谢大佬提供的思路和学习资料,该问题暂时得到解决,真心感谢orz。
感谢大佬的回复,本人初次接触嵌入式开发,对于这些基础仍需要查漏补缺orz。
衷心感谢指点!