本文将介绍K60(Freescale Kinetis K60)和XS128(Freescale S12XS128)的ADC用法。
K60使用了野火的12年版底层库,请参考《三天入门 Cortex-M4—Kinetis 系列 野火 Kinetics 开发板教程》。
XS128请参考飞思卡尔提供的Datasheet.
PWM模块产生脉冲,用于控制电机。通过改变其占空比,可以控制电机输出的大小。
脉冲计数(XS128的TIM)模块相当于一个计数器,可以对脉冲输入进行计数,用于测速编码器。
PWM输出和输入模块都不占用运算资源,只要配置好,它们就能自己工作。
K60的脉冲计数我忘了怎么做了,所以这里只提供XS128的方法。
K60 - PWM
电机初始化,初始化PWM输出。
/********************************************************************
** 函数名称: motor_init()
** 功能描述: 电机初始化
** 入口:
** 出口:
** 说明: 初始化PWM输出通道,设置输出频率,初始占空比。
*********************************************************************/
void motor_init()
{
//初始化FTM0_CH0 CH1 CH2 CH3输出频率为 16kHZ,占空比为 50% 的PWM;
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH0,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH0
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH1,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH1
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH2,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH2
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH3,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH3
}
** 函数名称: motor_init()
** 功能描述: 电机初始化
** 入口:
** 出口:
** 说明: 初始化PWM输出通道,设置输出频率,初始占空比。
*********************************************************************/
void motor_init()
{
//初始化FTM0_CH0 CH1 CH2 CH3输出频率为 16kHZ,占空比为 50% 的PWM;
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH0,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH0
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH1,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH1
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH2,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH2
FTM_PWM_init(MOTOR_FTMN,MOTOR_FTMCH3,MOTOR_FREQ,MOTOR_INIT_VAL); //初始化CH3
}
程序中可以随时调用以下函数来改变占空比
FTM_PWM_Duty(MOTOR_FTMN,MOTOR_FTMCH1,0); //设置CH1占空比为0 (没有输出)
FTM_PWM_Duty(MOTOR_FTMN,MOTOR_FTMCH2,5000); //设置CH2占空比为50%(精度是10000,所以5000就是50%)
FTM_PWM_Duty(MOTOR_FTMN,MOTOR_FTMCH2,5000); //设置CH2占空比为50%(精度是10000,所以5000就是50%)
用到的宏定义
#define MOTOR_FTMN FTM0 //使用FTM0模块,请参考野火手册
#define MOTOR_FTMCH0 CH0
#define MOTOR_FTMCH1 CH1
#define MOTOR_FTMCH2 CH2
#define MOTOR_FTMCH3 CH3
#define MOTOR_FREQ 16000 //电机频率 16KHz
#define MOTOR_INIT_VAL 5000 //电机初始值,精度1/10000 即5000/10000 50%
#define MOTOR_FTMCH0 CH0
#define MOTOR_FTMCH1 CH1
#define MOTOR_FTMCH2 CH2
#define MOTOR_FTMCH3 CH3
#define MOTOR_FREQ 16000 //电机频率 16KHz
#define MOTOR_INIT_VAL 5000 //电机初始值,精度1/10000 即5000/10000 50%
XS128 - PWM
XS128的PWM初始化需要仔细一点,因为有好多寄存器啊orz
先上代码,这里需要用到4个通道
/**************************************************
* 函数名称: void PWM_init()
* 功能描述: PWM初始化函数
* 说明:
***************************************************/
void PWM_init()
{
PWME = 0X00; //关闭通道使能
PWMPOL=0xff; //先输出高电平,计数到DTY时,反转电平
PWMCLK = 0xFF; //时钟源选择0145通道选择SA,2367SB
PWMPRCLK = 0X52; //A时钟4分频,B时钟32分频
//ClockA = fbus / 4; ClockB = fbus / 32;
PWMCAE=0x00; //选择输出模式为左对齐输出模式
PWMSCLA = 10; //SA = clockA /( 2 * PWMSCLA )
PWMSCLB = 1; //SB = clockB /( 2 * PWMSCLB )
PWMCTL_CON01=0; //通道不级联
PWMCTL_CON45=0; //通道不级联
PWMPER0 =(char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY0 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER1 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY1 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER4 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY4 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER5 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY5 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
// PWM输出频率计算
// PWMx Frequency = Clock (A, B, SA, or SB) / PWMPERx
// 0145通道使用了SA.
// Bus Freq = 80MHz
// Clock A Freq = 80MHz/4 = 20MHz
// Clock SA Freq = 20MHz/(2*10) = 1MHz
// PWM0 Freq = 1MHz/200 = 5KHz
// 电机脉冲输出频率为5KHz
//使能
PWME_PWME0 = 1;
PWME_PWME1 = 1;
PWME_PWME4 = 1;
PWME_PWME5 = 1;
}
* 函数名称: void PWM_init()
* 功能描述: PWM初始化函数
* 说明:
***************************************************/
void PWM_init()
{
PWME = 0X00; //关闭通道使能
PWMPOL=0xff; //先输出高电平,计数到DTY时,反转电平
PWMCLK = 0xFF; //时钟源选择0145通道选择SA,2367SB
PWMPRCLK = 0X52; //A时钟4分频,B时钟32分频
//ClockA = fbus / 4; ClockB = fbus / 32;
PWMCAE=0x00; //选择输出模式为左对齐输出模式
PWMSCLA = 10; //SA = clockA /( 2 * PWMSCLA )
PWMSCLB = 1; //SB = clockB /( 2 * PWMSCLB )
PWMCTL_CON01=0; //通道不级联
PWMCTL_CON45=0; //通道不级联
PWMPER0 =(char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY0 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER1 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY1 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER4 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY4 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
PWMPER5 =(unsigned char) 200; //PWMx Period = Channel Clock Period * (2 * PWMPERx)
PWMDTY5 = (unsigned char) 100; //Duty Cycle = [PWMDTYx / PWMPERx] * 100% 占空比=100/200=50%
// PWM输出频率计算
// PWMx Frequency = Clock (A, B, SA, or SB) / PWMPERx
// 0145通道使用了SA.
// Bus Freq = 80MHz
// Clock A Freq = 80MHz/4 = 20MHz
// Clock SA Freq = 20MHz/(2*10) = 1MHz
// PWM0 Freq = 1MHz/200 = 5KHz
// 电机脉冲输出频率为5KHz
//使能
PWME_PWME0 = 1;
PWME_PWME1 = 1;
PWME_PWME4 = 1;
PWME_PWME5 = 1;
}
PWM初始化后,程序可以直接改变PWMDTY0,PWMDTY1,PWMDTY4,PWMDTY5的值来改变输出的占空比。
PWMDTY0 = (unsigned char) 200; //设置通道0的占空比为100%
PWMDTY1 = (unsigned char) 0; //设置通道1的占空比为0
PWMDTY4 = (unsigned char) 200; // 设置通道4的占空比为100%
PWMDTY5 = (unsigned char) 0; //设置通道5的占空比为0
PWMDTY1 = (unsigned char) 0; //设置通道1的占空比为0
PWMDTY4 = (unsigned char) 200; // 设置通道4的占空比为100%
PWMDTY5 = (unsigned char) 0; //设置通道5的占空比为0
PWM的框图。每个通道时钟由Bus Clock经过分频得到,每个通道都有自己的计数器,有周期和占空比属性。
PWM通道时钟选择,1245通道时钟设置为0时用ClockA,设置为1时用ClockSA.
PWMPRCLK配置Clock A和Clock B的频率,它们由Bus Clock分频而得。
XS128 - 脉冲计数
初始化TIM计数
void TIM_Init(void)
{
/**************** For Encoder Counting ********************/
TCNT =0x00;
TSCR1=0x80; //TIMER 定时器使能
TSCR2 = 0x06; // Timer Prescale. Bus Clock/64
PACTL=0xc0; //PT7 PIN,PACN32 16BIT,FALLing edge,NO INTERRUPT 0xc0 = 1100 0000
TFLG1=0xFF; //清中断标志位
}
{
/**************** For Encoder Counting ********************/
TCNT =0x00;
TSCR1=0x80; //TIMER 定时器使能
TSCR2 = 0x06; // Timer Prescale. Bus Clock/64
PACTL=0xc0; //PT7 PIN,PACN32 16BIT,FALLing edge,NO INTERRUPT 0xc0 = 1100 0000
TFLG1=0xFF; //清中断标志位
}
读取计数值
//获得速度L
SPEED_EN_L = 0; //计数禁止
NowSpeedL = PACNT; //读取寄存器的值
PACNT = 0; //清零计数器
SPEED_EN_L = 1; //计数允许
SPEED_EN_L = 0; //计数禁止
NowSpeedL = PACNT; //读取寄存器的值
PACNT = 0; //清零计数器
SPEED_EN_L = 1; //计数允许