用TN4C123编写的光电编码程序用的是WTimer1的A B可是一个轮子转,一个轮子不转。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
是的,输出的是高低电平脉冲呀,光电编码器的原理啊,就是测量脉冲。
#include<stdint.h>
#include<stdbool.h>
#include"inc/tm4c123gh6pm.h"
#include"inc/hw_gpio.h"
#include"inc/hw_memmap.h"
#include"driverlib/sysctl.h"
#include"driverlib/gpio.h"
#include"driverlib/pin_map.h"
#include"driverlib/adc.h"
#include"driverlib/interrupt.h"
#include"driverlib/timer.h"
unsigned long aulTimes1=0;
unsigned long aulTimes2=0;
unsigned int aulFlag=0;
unsigned int aCaptuerSuccess=0;
unsigned int aCaptuerFalse=0;
unsigned long bulTimes1=0;
unsigned long bulTimes2=0;
unsigned int bulFlag=0;
unsigned int bCaptuerSuccess=0;
unsigned int bCaptuerFalse=0;
unsigned int P1=0,P2=0,Q1=0,W1=0;
void WT1A_BforPC6_7(void)
{
// Enable Peripheral Clocks 端口初始化
SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
//PC6端口初始化
GPIOPinConfigure(GPIO_PC6_WT1CCP0);
GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_6);
//PC7端口初始化
GPIOPinConfigure(GPIO_PC7_WT1CCP1);
GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_7);
TimerDisable(WTIMER1_BASE, TIMER_A);
TimerDisable(WTIMER1_BASE, TIMER_B);
TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_TIME|TIMER_CFG_B_CAP_TIME);
//捕获频率配置
// TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_TIME);//WT3设置为 分开模式 TimerA 边沿计时模式 减计数
TimerControlEvent(WTIMER1_BASE, TIMER_A,TIMER_EVENT_POS_EDGE);//WT1timerA设置为 上升沿触发
TimerLoadSet(WTIMER1_BASE, TIMER_A,900000000);//初始值为90000000(32位timerA4294967296的范围内)
TimerIntDisable(WTIMER1_BASE, TIMER_CAPA_EVENT|TIMER_TIMA_TIMEOUT);// 触发捕获模式中断 和 time out 中断
IntEnable(INT_WTIMER1A);//使能WT3timerA的中断
TimerDisable(WTIMER1_BASE,TIMER_A);//关闭WT3timerA
//捕获频率配置
// TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_CAP_TIME);//WT3设置为 分开模式 TimerB 边沿计时模式 减计数
TimerControlEvent(WTIMER1_BASE, TIMER_B,TIMER_EVENT_POS_EDGE);//WT3timerB设置为 上升沿触发
TimerLoadSet(WTIMER1_BASE, TIMER_B,900000000);//初始值为90000000(32位timerA的范围内)
TimerIntDisable(WTIMER1_BASE, TIMER_CAPB_EVENT|TIMER_TIMB_TIMEOUT);// 触发捕获模式中断 和 time out 中断
IntEnable(INT_WTIMER1B);//使能WT3timerA的中断
TimerDisable(WTIMER1_BASE,TIMER_B);//关闭WT3timerB
//开全局中断
//IntMasterEnable();
TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer
TimerEnable(WTIMER1_BASE, TIMER_A);
TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer
TimerEnable(WTIMER1_BASE, TIMER_B);
}
void TimeOut_T1B_T0AforPB5_6(void)
{
//配置捕获timeout定时器for左轮
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
TimerDisable(TIMER1_BASE, TIMER_B);
TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PERIODIC);
TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
IntEnable(INT_TIMER1B);
TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
// TimerEnable(TIMER1_BASE,TIMER_B);
//配置捕获timeout定时器for右轮
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
TimerDisable(TIMER0_BASE, TIMER_A);
TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PERIODIC);
TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
IntEnable(INT_TIMER0A);
TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// TimerEnable(TIMER0_BASE,TIMER_A);
TimerIntEnable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
TimerEnable(TIMER1_BASE, TIMER_B);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER0_BASE, TIMER_A);
}
void WTimer1A_ISR_CAP(void)//中断:WT1A:PC6左轮::使用标志a
{
unsigned long IntState;
IntState=TimerIntStatus(WTIMER1_BASE, true);//中断标志位获取
if(IntState&TIMER_TIMA_TIMEOUT)//中断由time out引起时的操作
{
SysCtlDelay(40);
//TimerIntClear(WTIMER1_BASE,TIMER_TIMA_TIMEOUT);
Q1=1;
}
if(IntState&TIMER_CAPA_EVENT)//中断由触发捕获引起时的操作
{
W1=1;
TimerIntClear(WTIMER1_BASE, TIMER_CAPA_EVENT);//清除中断标志
if( aulFlag==0)//当ulFlag==0时,当前中断获取值赋值给ulTimes1,并将ulFlag置1(此为第一次值)
{
aulTimes1=TimerValueGet(WTIMER1_BASE, TIMER_A);
aulFlag=1;
}
else//当ulFlag==1时,当前中断获取值赋值给ulTimes2,并将ulFlag置0(此为第二次值)
{
aulTimes2=TimerValueGet(WTIMER1_BASE, TIMER_A);
TimerIntDisable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer(即重新开始)
TimerDisable(WTIMER1_BASE, TIMER_A);
TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
TimerDisable(TIMER1_BASE, TIMER_B);
TimerLoadSet(WTIMER1_BASE, TIMER_A,900000000);//重新载入初始值(防止时间过长自动复位)
aulFlag=0;
aCaptuerSuccess=1;//两次值获取成功,获取完成将CaptuerSuccess置1
}
}
}
void WTimer1B_ISR_CAP(void)//中断:WT1B:PC7右轮::使用标志b
{
unsigned long IntState;
IntState=TimerIntStatus(WTIMER1_BASE, true);//中断标志位获取
if(IntState&TIMER_TIMB_TIMEOUT)//中断由time out引起时的操作,即是长时间无法捕获成功,也就是速度为0
{
SysCtlDelay(40);
//TimerIntClear(WTIMER1_BASE,TIMER_TIMB_TIMEOUT);
}
if(IntState&TIMER_CAPB_EVENT)//中断由触发捕获引起时的操作
{
TimerIntClear(WTIMER1_BASE, TIMER_CAPB_EVENT);//清除中断标志
if( bulFlag==0)//当ulFlag==0时,当前中断获取值赋值给ulTimes1,并将ulFlag置1(此为第一次值)
{
bulTimes1=TimerValueGet(WTIMER1_BASE, TIMER_B);
bulFlag=1;
}
else//当ulFlag==1时,当前中断获取值赋值给ulTimes2,并将ulFlag置0(此为第二次值)
{
bulTimes2=TimerValueGet(WTIMER1_BASE, TIMER_B);
TimerIntDisable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer(即重新开始)
TimerDisable(WTIMER1_BASE, TIMER_B);
TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerDisable(TIMER0_BASE, TIMER_A);
TimerLoadSet(WTIMER1_BASE, TIMER_B,900000000);//重新载入初始值(防止时间过长自动复位)
bulFlag=0;
bCaptuerSuccess=1;//两次值获取成功,获取完成将CaptuerSuccess置1
}
}
}
void Timer1B_ISR(void) //设置1s的时间检测捕获是否超时
{
unsigned long IntState;
IntState=TimerIntStatus(TIMER1_BASE, true);
TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
if(IntState&TIMER_TIMB_TIMEOUT)
{
P1=1;
aCaptuerSuccess=0;
aCaptuerFalse=1;
TimerIntDisable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer(即重新开始)
TimerDisable(WTIMER1_BASE, TIMER_A);
TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
TimerDisable(TIMER1_BASE, TIMER_B);
}
}
void Timer0A_ISR(void) //设置1s的时间检测捕获是否超时
{
unsigned long IntState;
IntState=TimerIntStatus(TIMER0_BASE, true);
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
if(IntState&TIMER_TIMA_TIMEOUT)
{
bCaptuerSuccess=0;
bCaptuerFalse=1;
TimerIntDisable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer(即重新开始)
TimerDisable(WTIMER1_BASE, TIMER_B);
TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerDisable(TIMER0_BASE, TIMER_A);
}
}
void PWM_L(unsigned long match,unsigned long load) //匹配值和初值::timerA 左轮
{
TimerLoadSet(WTIMER0_BASE, TIMER_A, load);//设置初值
TimerMatchSet(WTIMER0_BASE, TIMER_A, match);//设置匹配值
//TimerEnable(WTIMER0_BASE, TIMER_A);//使能 WTimer0 的 TimerA
}
void PWM_R(unsigned long match,unsigned long load) //匹配值和初值::timerB 右轮
{
TimerLoadSet(WTIMER0_BASE, TIMER_B, load);//设置初值
TimerMatchSet(WTIMER0_BASE, TIMER_B, match);//设置匹配值
//TimerEnable(WTIMER0_BASE, TIMER_B);//使能 WTimer0 的 TimerB
}
void dianjichushihua ()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE ,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4);
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4,0);
//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//GPIOPinTypeGPIOInput(GPIO_PORTE_BASE ,GPIO_PIN_1|GPIO_PIN_2);//红外线PE1 PE2口
SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
GPIOPinConfigure(GPIO_PC4_WT0CCP0);
GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_4);
GPIOPinConfigure(GPIO_PC5_WT0CCP1);
GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_5);
TimerDisable(WTIMER0_BASE, TIMER_A);
TimerDisable(WTIMER0_BASE, TIMER_B);
TimerConfigure(WTIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);
TimerControlLevel(WTIMER0_BASE, TIMER_A, true);
TimerMatchSet(WTIMER0_BASE, TIMER_A, 1);
TimerLoadSet(WTIMER0_BASE, TIMER_A, 50000);
TimerEnable(WTIMER0_BASE, TIMER_A);
TimerControlLevel(WTIMER0_BASE, TIMER_B, true);
TimerMatchSet(WTIMER0_BASE, TIMER_B, 1);
TimerLoadSet(WTIMER0_BASE, TIMER_B, 50000);
TimerEnable(WTIMER0_BASE, TIMER_B);
}
void dianjifangxiang(int a,int b)
{
if(a>0)
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,GPIO_PIN_1);//正转
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,0);
}
else if(a<0)
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,0);
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,GPIO_PIN_2);//反转
}
else
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,0);
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,0);
}
if(b>0)
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,GPIO_PIN_3);//正转
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,0);
}
else if(b<0)
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,0);//反转
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,GPIO_PIN_4);
}
else
{
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,0);
GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,0);
}
}
void dianjisudu(int a,int b)
{
if(a>50000||b>50000||a<0||b<0)
return;
TimerMatchSet(WTIMER0_BASE, TIMER_A, a);
TimerMatchSet(WTIMER0_BASE, TIMER_B, b);
}
void dianjikongzhi(int a,int b)
{
dianjifangxiang(a,b);
if(a<0)
a=-a;
if(b<0)
b=-b;
dianjisudu(a,b);
}
void main(void)
{
long Comp1=0,Comp2=0;
long match=20000,load=50000;
SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
//电机供电:
dianjichushihua();
dianjikongzhi(20000,20000);
WT1A_BforPC6_7();//初始化
//PWM_WT0A_BforPC4_5();
TimeOut_T1B_T0AforPB5_6();
PWM_L(match,load);
PWM_R(match,load);
//开全局中断
IntMasterEnable();
while(1)
{
if(aCaptuerSuccess==1) //a频率捕捉成功
{
Comp1=aulTimes1-aulTimes2;
aCaptuerSuccess=0;
TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//重新开始
TimerEnable(WTIMER1_BASE, TIMER_A);
TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
IntEnable(INT_TIMER1B);
TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
}
if(aCaptuerFalse==1) //a频率捕捉失败
{
P2=1;
Comp1=900000000;
aCaptuerFalse=0;
TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//重新开始
TimerEnable(WTIMER1_BASE, TIMER_A);
TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
IntEnable(INT_TIMER1B);
TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
}
if(bCaptuerSuccess==1) //b频率捕捉成功
{
Comp2=bulTimes1-bulTimes2;
bCaptuerSuccess=0;
TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//重新开始
TimerEnable(WTIMER1_BASE, TIMER_B);
TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
IntEnable(INT_TIMER0A);
TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
if(bCaptuerFalse==1) //b频率捕捉失败
{
bCaptuerFalse=0;
Comp2=900000000;
TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//重新开始
TimerEnable(WTIMER1_BASE, TIMER_B);
TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
IntEnable(INT_TIMER0A);
TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
if(Comp1>Comp2)//左轮慢时:数值小代表 间隔小,速度快
{
match+=100;//步进为100
if(match>load)
match=load;
if(match<0)
match=0;
PWM_L(match,load);
}
if(Comp1<Comp2)//左轮快时
{
match-=100;//步进为100
if(match>load)
match=load;
if(match<0)
match=0;
PWM_L(match,load);
}
}
}