云计算百科
云计算领域专业知识百科平台

震动马达实现库函数版(STC8)

震动马达实现库函数版(STC8)

硬件连接

震动马达通常连接在单片机的PWM输出引脚上,例如P1.5(对应PWM2通道)。需确保马达驱动电路包含三极管或MOS管放大电流,并反向并联续流二极管保护。

STC8 PWM库函数配置

#include "GPIO.h"
#include"Delay.h"
#include "UART.h"// 串口配置 UART_Configuration
#include "NVIC.h"// 中断初始化NVIC_UART1_Init
#include "Switch.h" // 引脚切换 UART1_SW_P30_P31
#include "STC8H_PWM.h"

// 宏定义,给引脚起别名
#define MOTOR P01

void GPIO_config() {
GPIO_InitTypeDef info;
// ===== UART1 P30 P31 准双向
info.Mode = GPIO_PullUp; // 准双向
info.Pin = GPIO_Pin_0 | GPIO_Pin_1; // 引脚
GPIO_Inilize(GPIO_P3, &info);

//推挽输出P01
P0_MODE_OUT_PP(GPIO_Pin_1); // 推挽输出默认是高电平
MOTOR = 0; // 建议拉低
}

// 串口配置函数的定义
void UART_config(void) {
// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
COMx_InitDefineCOMx_InitStructure;//结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx;//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer1;//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
COMx_InitStructure.UART_BaudRate = 115200ul;//波特率, 一般 110 ~ 115200
COMx_InitStructure.UART_RxEnable = ENABLE;//接收允许, ENABLE或DISABLE
COMx_InitStructure.BaudRateDouble = DISABLE;//波特率加倍, ENABLE或DISABLE
UART_Configuration(UART1, &COMx_InitStructure);//初始化串口1 UART1,UART2,UART3,UART4

NVIC_UART1_Init(ENABLE,Priority_1);//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
UART1_SW(UART1_SW_P30_P31);// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

// PWMB 配置
#define PERIOD (MAIN_Fosc / 1000)
voidPWM_config(void)
{
PWMx_InitDefinePWMx_InitStructure;
// 配置PWM6
PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1;//模式,CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
PWMx_InitStructure.PWM_Duty = 0.0 * PERIOD;//PWM占空比时间, 0~Period
PWMx_InitStructure.PWM_EnoSelect = ENO6P;//输出通道选择,ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
PWM_Configuration(PWM6, &PWMx_InitStructure);//初始化PWM, PWMA,PWMB

// 配置PWMB
PWMx_InitStructure.PWM_Period = PERIOD 1;//周期时间, 0~65535
PWMx_InitStructure.PWM_DeadTime = 0;//死区发生器设置, 0~255
PWMx_InitStructure.PWM_MainOutEnable= ENABLE;//主输出使能, ENABLE,DISABLE
PWMx_InitStructure.PWM_CEN_Enable = ENABLE;//使能计数器, ENABLE,DISABLE
PWM_Configuration(PWMB, &PWMx_InitStructure);//初始化PWM通用寄存器, PWMA,PWMB

// 切换PWM通道
PWM6_SW(PWM6_SW_P01);//PWM6_SW_P21,PWM6_SW_P54,PWM6_SW_P01,PWM6_SW_P75

// 初始化PWMB的中断
NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}

// 更新PWM占空比
void Update_pwm_duty(char value) { // 0 ~ 100
PWMx_Duty duty;
duty.PWM6_Duty = (value / 100.0) * PERIOD;
UpdatePwm(PWM6, &duty);
}

void main() {
char i = 0;
EAXSFR();/* 扩展寄存器访问使能 */
EA = 1; // 使能中断总开关

GPIO_config(); // GPIO配置
UART_config(); // 串口配置
PWM_config(); // 调用PWM配置

// 逐渐增强
for(i = 0; i <= 100; i += 5) {
Update_pwm_duty(i);
delay_ms(250);
}
Update_pwm_duty(0);

while (1){
}
}

震动强度控制

通过修改占空比寄存器控制震动强度:

// 更新PWM占空比
void Update_pwm_duty(char value) { // 0 ~ 100
PWMx_Duty duty;
duty.PWM6_Duty = (value / 100.0) * PERIOD;
UpdatePwm(PWM6, &duty);
}

定时震动模式

利用定时器实现间歇震动:

void Timer0_ISR()
{
static uint8_t counter = 0;
if(++counter >= 20) { // 约1秒切换状态
counter = 0;
PWMB_CCER2 ^= 0x01; // 切换PWM输出状态
}
}

案例

#include "GPIO.h"
#include"Delay.h"
#include "UART.h"
#include "NVIC.h"
#include "Switch.h"
#include "STC8H_PWM.h"
#include"Timer.h"

#define MOTOR P01
int i = 0;

void GPIO_config(void) {

GPIO_InitTypeDefGPIO_InitStructure;//结构定义
GPIO_InitStructure.Pin = GPIO_Pin_0 |GPIO_Pin_1;//指定要初始化的IO,
GPIO_InitStructure.Mode = GPIO_PullUp;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化

//推挽输出P01
P0_MODE_OUT_PP(GPIO_Pin_1);

MOTOR = 0 ;
}
void UART_config(void) {
// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
COMx_InitDefineCOMx_InitStructure;//结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx;//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer1;//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
COMx_InitStructure.UART_BaudRate = 115200ul;//波特率, 一般 110 ~ 115200
COMx_InitStructure.UART_RxEnable = ENABLE;//接收允许, ENABLE或DISABLE
COMx_InitStructure.BaudRateDouble = DISABLE;//波特率加倍, ENABLE或DISABLE
UART_Configuration(UART1, &COMx_InitStructure);//初始化串口1 UART1,UART2,UART3,UART4

NVIC_UART1_Init(ENABLE,Priority_1);//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
UART1_SW(UART1_SW_P30_P31);// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

#define PERIOD (MAIN_Fosc / 1000)
voidPWM_config(void)
{
PWMx_InitDefinePWMx_InitStructure;
// 配置PWM6
PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1;//模式,CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
PWMx_InitStructure.PWM_Duty = 0.0 * PERIOD;//PWM占空比时间, 0~Period
PWMx_InitStructure.PWM_EnoSelect = ENO6P;//输出通道选择,ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
PWM_Configuration(PWM6, &PWMx_InitStructure);//初始化PWM, PWMA,PWMB
// 配置PWMB
PWMx_InitStructure.PWM_Period = PERIOD 1;//周期时间, 0~65535
PWMx_InitStructure.PWM_DeadTime = 0;//死区发生器设置, 0~255
PWMx_InitStructure.PWM_MainOutEnable= ENABLE;//主输出使能, ENABLE,DISABLE
PWMx_InitStructure.PWM_CEN_Enable = ENABLE;//使能计数器, ENABLE,DISABLE
PWM_Configuration(PWMB, &PWMx_InitStructure);//初始化PWM通用寄存器, PWMA,PWMB

// 切换PWM通道
PWM6_SW(PWM6_SW_P01);//PWM6_SW_P21,PWM6_SW_P54,PWM6_SW_P01,PWM6_SW_P75
// 初始化PWMB的中断
NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}
void pwm_set_duty(char value){
PWMx_Duty duty ;
duty.PWM6_Duty = (value/100.0)*PERIOD;
UpdatePwm(PWM6, &duty);

}
voidTimer_config(void)
{
TIM_InitTypeDefTIM_InitStructure;//结构定义
//定时器0做16位自动重装, 中断频率为1000HZ
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload;//指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;//指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE;//是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 65536UL (MAIN_Fosc / 1000UL);//初值,
TIM_InitStructure.TIM_Run = ENABLE;//是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer0,&TIM_InitStructure);//初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
NVIC_Timer0_Init(ENABLE,Priority_0);//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
// 更新PWM占空比
void Update_pwm_duty(char value) { // 0 ~ 100
PWMx_Duty duty;
duty.PWM6_Duty = (value / 100.0) * PERIOD;
UpdatePwm(PWM6, &duty);
}
void timer0_call(){
// TODO: 在此处添加用户代码
i++;
if (i == 10000) { // 1000个1ms才进入1次 每隔1s,震动1次
P01 = !P01;
Update_pwm_duty(i);
printf("i = %d\\r\\n",i);

i = 0; // 重置
}
}
void main() {
EAXSFR ();
EA = 1;
GPIO_config();
UART_config();
PWM_config();
Timer_config();
while (1){
}
}

注意事项

  • 需根据实际马达工作电压调整PWM频率(通常500Hz-2kHz)
  • 马达两端建议并联0.1μF电容滤波
  • 长时间工作时需注意散热
  • STC8系列需先设置I/O口模式再配置PWM
  • 典型调用示例

    1.串口结合pwm控制震动马达

    #include"GPIO.h"
    #include"Delay.h"
    #include"STC8H_PWM.h"
    #include"NVIC.h"
    #include"Switch.h"
    #include "UART.h"

    void GPIO_config(void) {
    GPIO_InitTypeDefGPIO_InitStructure;//结构定义
    // UART1: P30 P31 准双向口
    GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1;//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化

    // P01 推挽输出
    GPIO_InitStructure.Pin = GPIO_Pin_1;//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P0, &GPIO_InitStructure);//初始化
    }

    // 1000为频率,1秒钟执行1000次
    #define PERIOD (MAIN_Fosc / 1000)

    voidPWM_config(void)
    {
    PWMx_InitDefinePWMx_InitStructure;

    // 配置PWM6
    PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1;//模式,CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
    PWMx_InitStructure.PWM_Duty = 0;//PWM占空比时间, 0~Period
    PWMx_InitStructure.PWM_EnoSelect = ENO6P;//输出通道选择,ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
    PWM_Configuration(PWM6, &PWMx_InitStructure);//初始化PWM, PWMA,PWMB

    // 配置PWMB
    PWMx_InitStructure.PWM_Period = PERIOD 1;//周期时间, 0~65535
    PWMx_InitStructure.PWM_DeadTime = 0;//死区发生器设置, 0~255
    PWMx_InitStructure.PWM_MainOutEnable= ENABLE;//主输出使能, ENABLE,DISABLE
    PWMx_InitStructure.PWM_CEN_Enable = ENABLE;//使能计数器, ENABLE,DISABLE
    PWM_Configuration(PWMB, &PWMx_InitStructure);//初始化PWM通用寄存器, PWMA,PWMB

    // 切换PWM通道
    PWM6_SW(PWM6_SW_P01);//PWM6_SW_P21,PWM6_SW_P54,PWM6_SW_P01,PWM6_SW_P75

    // 初始化PWMB的中断
    NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
    }

    void UART_config(void) {
    // >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
    COMx_InitDefineCOMx_InitStructure;//结构定义
    COMx_InitStructure.UART_Mode = UART_8bit_BRTx;//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use = BRT_Timer1;//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate = 115200ul;//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable = ENABLE;//接收允许, ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);//初始化串口1 UART1,UART2,UART3,UART4

    NVIC_UART1_Init(ENABLE,Priority_1);//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_SW(UART1_SW_P30_P31);// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
    }

    void on_uart1_recv(u8 buf1) {
    // 静态变量,只会初始化1次,不释放
    static PWMx_Duty duty; // 占空比结构体变量
    static char d = 100;

    // 串口不断接收到0x1,震动逐渐减弱,如果是停止,震动强度从最强的模式重来
    if (buf1 == 0x01) { // 减少占空比
    d -= 5;
    if (d < 0) { // < 0时,重新开始
    d = 100;
    }
    }

    printf("d = %d\\n", (int)d);

    // 设置比例数字
    duty.PWM6_Duty = d * PERIOD / 100.0;
    // 更新占空比
    UpdatePwm(PWM6, &duty);
    }

    void main() {
    u8 d = 0, i;

    EAXSFR();/* 扩展寄存器访问使能 */
    // IO配置
    GPIO_config();
    PWM_config();
    UART_config();

    // 开启全局中断
    EA = 1;

    while (1) {
    delay_ms(20);

    if(COM1.RX_TimeOut > 0) {
    //超时计数
    if(COM1.RX_TimeOut == 0) {
    if(COM1.RX_Cnt > 0) {
    for(i=0; i<COM1.RX_Cnt; i++){
    // RX1_Buffer[i]存的是接收的数据,写出用 TX1_write2buff
    // TODO: 做具体的逻辑
    TX1_write2buff(RX1_Buffer[i]); // 原数据发送

    on_uart1_recv(RX1_Buffer[i]);

    }
    }
    COM1.RX_Cnt = 0;
    }
    }

    }
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 震动马达实现库函数版(STC8)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!