` 大家周末好!不知不觉已经过去一个月了,今天再与大家谈谈KE16Z开发板使用的心得体会。关于该开发板的特性,想必大家都已经熟悉,官方给出的SDK入门操作手册是基于MCUXpresso IDE介绍的,本人使用的是MDK,这一点没什么影响,SDK中有提供IAR、MDK的参考设计源码,本想是很成熟的开发套件,但实际运用起来不是那么顺。给出的“touch_sensing”工程,下载到开发板中,串口是没有信息输出,RGB的D4指示灯是狂闪,再去触摸板上的两个触摸按键,没有任何响应,不知道所为何故。
再者验证其它低功耗,RTC,BLDC工程需要借助外部工具。BLDC工程是提供了,但没有电机驱动板,所以得自己选型购买。如上图的步进电机,至少得要个大功率的驱动板才能控制吧。之前使用过英飞凌的TLE9879开发板,它就是一块开发板带集成驱动电路,而且是支持三相输出。
我们进行的光磁检测设备,方案选型大致已敲定,使用的是 STM32的战舰开发板,没错,ST官方给出资料比较详细,网上资源丰富。代码基本上调试的差不多了,因此希望NXP KE16Z开发板有比较完备的参考设计套件。该项目用到的步进电机采用36V输出的驱动板驱动。
驱动控制板也是市面上常用的
使用的芯片型号是STM32F407ZGT6
部分的参考代码如下:
- #include "MicroStepDriver.h"
- #include
- #include
- //系统加减速参数
- speedRampData srd;
- //记录步进电机的位置
- int stepPosition = 0;
- //系统电机、串口状态
- struct GLOBAL_FLAGS status = {FALSE, FALSE,TRUE};
- extern volatile char DIR_flag;
- /**
- * [url=home.php?mod=space&uid=2666770]@Brief[/url] 定时器中断优先级配置
- * [url=home.php?mod=space&uid=3142012]@param[/url] 无
- * @retval 无
- */
- static void TIM_NVIC_Config(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- // 设置中断来源
- NVIC_InitStructure.NVIC_IRQChannel = MSD_PULSE_TIM_IRQ;
- // 设置抢占优先级
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- // 设置子优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /**
- * @brief 初始化电机驱动用到的引脚
- * @param 无
- * @retval 无
- */
- static void MSD_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //电机脉冲输出 GPIO 初始化
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //GPIOE使能
- GPIO_InitStructure.GPIO_Pin = MSD_PULSE_PIN;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(MSD_PULSE_PORT, &GPIO_InitStructure);
- GPIO_PinAFConfig(MSD_PULSE_PORT,MSD_PULSE_PIN_SOURCE,MSD_PULSE_PIN_AF); /* 连接 PXx 到 定时器输出通道*/
-
- //电机方向输出 GPIO 初始化
- MSD_DIR_AHBxClock_FUN(MSD_DIR_GPIO_CLK, ENABLE);
- GPIO_InitStructure.GPIO_Pin = MSD_DIR_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(MSD_DIR_PORT, &GPIO_InitStructure);
- GPIO_ResetBits(MSD_DIR_PORT,MSD_DIR_PIN);
-
- //电机使能输出 GPIO 初始化
- MSD_ENA_AHBxClock_FUN(MSD_ENA_GPIO_CLK, ENABLE);
- GPIO_InitStructure.GPIO_Pin = MSD_ENA_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(MSD_ENA_PORT, &GPIO_InitStructure);
- GPIO_ResetBits(MSD_ENA_PORT,MSD_ENA_PIN);
- //GPIO_SetBits(MSD_ENA_PORT,MSD_ENA_PIN);
-
- }
- /* ---------------- PWM信号 周期和占空比的计算--------------- */
- // ARR :自动重装载寄存器的值
- // CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 180M/(psc+1)
- // PWM 信号的周期 T = (ARR+1) * (1/CLK_cnt) = (ARR+1)*(PSC+1) / 72M
- // 占空比P=CCR/(ARR+1)
- static void TIM_Mode_Config(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- // 开启定时器时钟,即内部时钟CK_INT=180M
- MSD_PULSE_TIM_APBxClock_FUN(MSD_PULSE_TIM_CLK,ENABLE);
- /*--------------------时基结构体初始化-------------------------*/
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- // 自动重装载寄存器的值,累计TIM_Period+1个周期后产生一个更新或者中断
- TIM_TimeBaseStructure.TIM_Period=MSD_PULSE_TIM_PERIOD;
- // 驱动CNT计数器的时钟 = Fck_int/(psc+1)
- TIM_TimeBaseStructure.TIM_Prescaler= MSD_PULSE_TIM_PSC;
- // 时钟分频因子 ,配置死区时间时需要用到
- TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
- // 计数器计数模式,设置为向上计数
- TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
- // 重复计数器的值,最大值为255
- //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
- // 初始化定时器
- TIM_TimeBaseInit(MSD_PULSE_TIM, &TIM_TimeBaseStructure);
- /*--------------------输出比较结构体初始化-------------------*/
- // 配置为PWM模式2
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
- // 输出使能
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- // 互补输出禁能
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
- // 设置占空比大小
- TIM_OCInitStructure.TIM_Pulse = MSD_PULSE_TIM_PERIOD/2;
- // 输出通道电平极性配置
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- // 输出通道空闲电平极性配置
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
- MSD_PULSE_OCx_Init(MSD_PULSE_TIM, &TIM_OCInitStructure);
- //使能TIM1_CH1预装载寄存器
- MSD_PULSE_OCx_PreloadConfig(MSD_PULSE_TIM, TIM_OCPreload_Enable);
- //使能TIM1预装载寄存器
- TIM_ARRPreloadConfig(MSD_PULSE_TIM, ENABLE);
- //设置中断源,只有溢出时才中断
- TIM_UpdateRequestConfig(MSD_PULSE_TIM,TIM_UpdateSource_Regular);
- // 清除中断标志位
- TIM_ClearITPendingBit(MSD_PULSE_TIM, TIM_IT_Update);
- // 使能中断
- TIM_ITConfig(MSD_PULSE_TIM, TIM_IT_Update, ENABLE);
- // 使能计数器
- TIM_Cmd(MSD_PULSE_TIM, DISABLE);
- }
- /**
- * @brief 初始化电机相关的外设
- * @param 无
- * @retval 无
- */
- void MSD_Init(void)
- {
- MSD_GPIO_Config();
- TIM_NVIC_Config();
- TIM_Mode_Config();
- }
- /**
- * @brief 驱动器紧急停止
- * @param NewState:使能或者禁止
- * @retval 无
- */
- void MSD_ENA(FunctionalState NewState)
- {
- if(NewState)
- {
- //ENA失能,禁止驱动器输出
- GPIO_SetBits(MSD_ENA_PORT,MSD_ENA_PIN);
- //紧急停止标志位为真
- status.out_ena = FALSE;
- //printf("
驱动器禁止输出(脱机状态)此时电机为无保持力矩状态,可以手动旋转电机");
- }
- else
- {
- //ENA使能
- GPIO_ResetBits(MSD_ENA_PORT,MSD_ENA_PIN);
- //紧急停止标志位为假
- status.out_ena = TRUE;
- //printf("
驱动器恢复运行,此时电机为保持力矩状态,此时串口指令可以正常控制电机");
- }
- }
- /*! rief 以给定的步数移动步进电机
- * 通过计算加速到最大速度,以给定的步数开始减速
- * 如果加速度和减速度很小,步进电机会移动很慢,还没达到最大速度就要开始减速
- * param step 移动的步数 (正数为顺时针,负数为逆时针).
- * param accel 加速度,如果取值为100,实际值为100*0.01*rad/sec^2=1rad/sec^2
- * param decel 减速度,如果取值为100,实际值为100*0.01*rad/sec^2=1rad/sec^2
- * param speed 最大速度,如果取值为100,实际值为100*0.01*rad/sec=1rad/sec
- */
- void MSD_Move(signed int step, unsigned int accel, unsigned int decel, unsigned int speed)
- {
- //达到最大速度时的步数.
- unsigned int max_s_lim;
- //必须开始减速的步数(如果还没加速到达最大速度时)。
- unsigned int accel_lim;
- // 根据步数的正负来判断方向
- if(step < 0)//逆时针
- {
- srd.dir = CCW;
- step = -step;
- }
- else//顺时针
- {
- srd.dir = CW;
- }
- // 输出电机方向
- DIR(srd.dir);
- // 配置电机为输出状态
- status.out_ena = TRUE;
- // 如果只移动一步
- if(step == 1)
- {
- // 只移动一步
- srd.accel_count = -1;
- // 减速状态
- srd.run_state = DECEL;
- // 短延时
- srd.step_delay = 1000;
- // 配置电机为运行状态
- status.running = TRUE;
- //设置定时器重装值
- TIM_SetAutoreload(MSD_PULSE_TIM,Pulse_width);
- //设置占空比为50%
- TIM_SetCompare2(MSD_PULSE_TIM,Pulse_width>>1);
- //使能定时器
- TIM_Cmd(MSD_PULSE_TIM, ENABLE);
- }
- // 步数不为零才移动
- else if(step != 0)
- {
- // 我们的驱动器用户手册有详细的计算及推导过程
- // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
- // min_delay = (alpha / tt)/ w
- srd.min_delay = A_T_x100 / speed;
- // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.01rad/sec^2
- // step_delay = 1/tt * sqrt(2*alpha/accel)
- // step_delay = ( tfreq*0.676/100 )*100 * sqrt( (2*alpha*10000000000) / (accel*100) )/10000
- srd.step_delay = (T1_FREQ_148 * sqrt(A_SQ / accel))/100;
- // 计算多少步之后达到最大速度的限制
- // max_s_lim = speed^2 / (2*alpha*accel)
- max_s_lim = (long)speed*speed/(long)(((long)A_x20000*accel)/100);
- // 如果达到最大速度小于0.5步,我们将四舍五入为0
- // 但实际我们必须移动至少一步才能达到想要的速度
- if(max_s_lim == 0)
- {
- max_s_lim = 1;
- }
- // 计算多少步之后我们必须开始减速
- // n1 = (n1+n2)decel / (accel + decel)
- accel_lim = ((long)step*decel) / (accel+decel);
- // 我们必须加速至少1步才能才能开始减速.
- if(accel_lim == 0)
- {
- accel_lim = 1;
- }
- // 使用限制条件我们可以计算出第一次开始减速的位置
- //srd.decel_val为负数
- if(accel_lim <= max_s_lim)
- {
- srd.decel_val = accel_lim - step;
- }
- else
- {
- srd.decel_val = -(long)(max_s_lim*accel/decel);
- }
- // 当只剩下一步我们必须减速
- if(srd.decel_val == 0)
- {
- srd.decel_val = -1;
- }
- // 计算开始减速时的步数
- srd.decel_start = step + srd.decel_val;
- // 如果最大速度很慢,我们就不需要进行加速运动
- if(srd.step_delay <= srd.min_delay)
- {
- srd.step_delay = srd.min_delay;
- srd.run_state = RUN;
- }
- else
- {
- srd.run_state = ACCEL;
- }
- // 复位加速度计数值
- srd.accel_count = 0;
- status.running = TRUE;
- //设置定时器重装值
- TIM_SetAutoreload(MSD_PULSE_TIM,Pulse_width);
- //设置占空比为50%
- TIM_SetCompare2(MSD_PULSE_TIM,Pulse_width>>1);
- //使能定时器
- TIM_Cmd(MSD_PULSE_TIM, ENABLE);
- }
- }
- /**
- * @brief 根据运动方向判断步进电机的运行位置
- * @param inc 运动方向
- * @retval 无
- */
- void MSD_StepCounter(signed char inc)
- {
- //根据方向判断电机位置
- if(inc == CCW)
- {
- stepPosition--;
- }
- else
- {
- stepPosition++;
- }
- }
- /**
- * @brief 产生脉冲定时器的中断响应程序,每走一步都会计算运动状态
- * @param 无
- * @retval 无
- */
- void MSD_PULSE_TIM_IRQHandler(void)
- {
- // 保存下一个延时周期
- unsigned int new_step_delay;
- // 加速过程中最后一次延时.
- static int last_accel_delay;
- // 移动步数计数器
- static unsigned int step_count = 0;
- // 记录new_step_delay中的余数,提高下一步计算的精度
- static signed int rest = 0;
- if (TIM_GetITStatus(MSD_PULSE_TIM, TIM_IT_Update) != RESET)
- {
- /* Clear MSD_PULSE_TIM Capture Compare1 interrupt pending bit*/
- TIM_ClearITPendingBit(MSD_PULSE_TIM, TIM_IT_Update);
- MSD_PULSE_TIM->CCR4=srd.step_delay >> 1;//周期的一半
- MSD_PULSE_TIM->ARR=srd.step_delay;
- //如果禁止输出,电机则停止运动
- if(status.out_ena != TRUE)
- {
- srd.run_state = STOP;
- }
- switch(srd.run_state) {
- case STOP:
- step_count = 0;
- rest = 0;
- MSD_PULSE_TIM->CCER &= ~(1<<12); //禁止输出
- TIM_Cmd(MSD_PULSE_TIM, DISABLE);
- status.running = FALSE;
- break;
- case ACCEL:
- MSD_PULSE_TIM->CCER |= 1<<12; //使能输出
- MSD_StepCounter(srd.dir);
- step_count++;
- srd.accel_count++;
- new_step_delay = srd.step_delay - (((2 * (long)srd.step_delay)
- + rest)/(4 * srd.accel_count + 1));
- rest = ((2 * (long)srd.step_delay)+rest)%(4 * srd.accel_count + 1);
- //检查是够应该开始减速
- if(step_count >= srd.decel_start) {
- srd.accel_count = srd.decel_val;
- srd.run_state = DECEL;
- }
- //检查是否到达期望的最大速度
- else if(new_step_delay <= srd.min_delay) {
- last_accel_delay = new_step_delay;
- new_step_delay = srd.min_delay;
- rest = 0;
- srd.run_state = RUN;
- }
- break;
- case RUN:
- MSD_PULSE_TIM->CCER |= 1<<12; //使能输出
- MSD_StepCounter(srd.dir);
- step_count++;
- new_step_delay = srd.min_delay;
- //检查是否需要开始减速
- if(step_count >= srd.decel_start) {
- srd.accel_count = srd.decel_val;
- //以最后一次加速的延时作为开始减速的延时
- new_step_delay = last_accel_delay;
- srd.run_state = DECEL;
- }
- break;
- case DECEL:
- MSD_PULSE_TIM->CCER |= 1<<12; //使能输出
- MSD_StepCounter(srd.dir);
- step_count++;
- srd.accel_count++;
- new_step_delay = srd.step_delay - (((2 * (long)srd.step_delay)
- + rest)/(4 * srd.accel_count + 1));
- rest = ((2 * (long)srd.step_delay)+rest)%(4 * srd.accel_count + 1);
- //检查是否为最后一步
- if(srd.accel_count >= 0){
- srd.run_state = STOP;
- }
- break;
- }
- srd.step_delay = new_step_delay;
- }
- }
- /**
- * @brief 配置嵌套向量中断控制器NVIC
- * @param 无
- * @retval 无
- */
- static void NVIC_Configuration(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- /* 配置中断源:按键1 */
- NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
- /* 配置抢占优先级:1 */
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- /* 配置子优先级:1 */
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- /* 使能中断通道 */
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- /* 配置中断源:按键2,其他使用上面相关配置 */
- NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
- NVIC_Init(&NVIC_InitStructure);
- }
- /**
- * @brief 配置 PA0 为线中断口,并设置中断优先级
- * @param 无
- * @retval 无
- */
- void EXTI_Key_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- EXTI_InitTypeDef EXTI_InitStructure;
-
- /*开启按键GPIO口的时钟*/
- RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK|KEY3_INT_GPIO_CLK ,ENABLE);
- /* 使能 SYSCFG 时钟 ,使用GPIO外部中断时必须使能SYSCFG时钟*/
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- /* 配置 NVIC */
- NVIC_Configuration();
- /* 限位开关 1的引脚 PE4*/
- GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
- /* 设置引脚为输入模式 */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
- /* 设置引脚不上拉也不下拉 */
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- /* 使用上面的结构体初始化按键 */
- GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
- /* 连接 EXTI 中断源 到key1引脚 */
- SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
- /* 选择 EXTI 中断源 */
- EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
- /* 中断模式 */
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- /* 上升沿触发 */
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
- /* 使能中断/事件线 */
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- /* 限位开关 2的引脚 PE5*/
- GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
- /* 其他配置与上面相同 */
- GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
- /* 连接 EXTI 中断源 到key2 引脚 */
- SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);
- /* 选择 EXTI 中断源 */
- EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- /* 下降沿触发 */
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- /*进钞按键开关 PA4*/
- GPIO_InitStructure.GPIO_Pin = KEY3_INT_GPIO_PIN;
- /* 设置引脚为输入模式 */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
- /* 设置引脚不上拉也不下拉 */
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- /* 使用上面的结构体初始化按键 */
- GPIO_Init(KEY3_INT_GPIO_PORT, &GPIO_InitStructure);
- }
- /**
- * @brief This function handles TIM2 interrupt request.
- * @param None
- * @retval None
- */
- void KEY1_IRQHandler(void)
- {
- //确保是否产生了EXTI Line中断
- if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
- {
- DIR_flag=1;
- //清除中断标志位
- EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
- }
- }
- void KEY2_IRQHandler(void)
- {
- //确保是否产生了EXTI Line中断
- if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)
- {
- if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==0)
- {
- DIR_flag=2;
- }
- //清除中断标志位
- EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
- }
- }
复制代码
- #include "main.h"
- #include "stm32f4xx.h"
- #define MOTOR_DEFAULT_SPEED 180
- unsigned char IsLockClosed(void)
- {
- return !GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2);
- }
- unsigned char IsLockOpen(void)
- {
- return !GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2);
- }
- void Motor_Stop(void)
- {
- TIM_SetCompare1(TIM1, 0);
- TIM_SetCompare4(TIM1, 0);
- delay_ms(20);
- TIM_Cmd(TIM1, DISABLE);
- }
- void Motor_Forward(void)
- {
- unsigned short pulse;
- pulse = MOTOR_DEFAULT_SPEED;
- TIM_SetCompare1(TIM1, 0);
- TIM_SetCompare4(TIM1, pulse);
- TIM_Cmd(TIM1, ENABLE);
- delay_ms(200);
- }
- void Motor_Backward(void)
- {
- unsigned short pulse;
- pulse = MOTOR_DEFAULT_SPEED;
- TIM_SetCompare1(TIM1, pulse);
- TIM_SetCompare4(TIM1, 0);
- TIM_Cmd(TIM1, ENABLE);
- }
- void Motor_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
- TIM_OCInitTypeDef TIM_OCInitStruct;
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
-
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_TIM1);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
- GPIO_Init(GPIOA, &GPIO_InitStructure); //PA8和PA11控制电机正反转(通过PWM控制转速)
-
- TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
- TIM_OCStructInit(&TIM_OCInitStruct);
-
- TIM_TimeBaseStruct.TIM_Prescaler = 168 - 1;
- TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStruct.TIM_Period = 200 - 1;
- TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStruct); //5KHz
-
- TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable;
- TIM_OCInitStruct.TIM_Pulse = 0;
- TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_Low;
- TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
- TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCIdleState_Reset;
-
- TIM_OC1Init(TIM1, &TIM_OCInitStruct);
- TIM_OC4Init(TIM1, &TIM_OCInitStruct);
-
- TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
- TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
-
- TIM_ARRPreloadConfig(TIM1, ENABLE);
- TIM_CtrlPWMOutputs(TIM1, ENABLE); //两路PWM只配置不启动定时器,相应引脚输出低电平
- TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);
- TIM_CCxCmd(TIM1, TIM_Channel_4, TIM_CCx_Enable);
- }
- void Position_Detect(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
- GPIO_Init(GPIOC, &GPIO_InitStructure); //PC2用于检测位置
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource2);
- EXTI_InitStructure.EXTI_Line = EXTI_Line2;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
-
- NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- void EXTI2_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line2) != RESET)
- {
- EXTI_ClearITPendingBit(EXTI_Line2);
- if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0)
- {
- delay_ms(10);
- if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0)
- {
- Motor_Stop();
- }
- }
- }
-
- }
复制代码
虽然没有使用KE16Z开发板进行磁光检查项目的开发,但也收获颇丰,该项目不仅仅需要电机驱动板,滑块平台,还需要AD板,希望后续有新的电机控制项目,将考虑使用NXP KE16Z设计开发。不管怎么样,再次感谢大联大世平提供的开发板,也感谢 电子发烧友技术交流平台。
`
|