|
|
#include "pwm.h"
#include "board.h"
#define CLCK 48
uint32_t target_frequencyhz; uint32_t target_duty;
static double calculate_top(double target_frequency_hz) { int clck = 0; int top = 0; clck = CLCK * 1000 * 1000; top = clck / target_frequency_hz; return top; }
void t16_pa4_init(void) { T16Nx_Disable(T16N0); // PA4 T16N0_1
T16Nx_BaseInitStruType x; T16Nx_PWMInitStruType y; /* 初始化T16Nx定时器*/ x.T16Nx_ClkS = T16Nx_ClkS_PCLK; //时钟源48M
x.T16Nx_SYNC = Disable; //不同步
x.T16Nx_EDGE = T16Nx_EDGE_Rise; //上升沿触发
x.T16Nx_Mode = T16Nx_Mode_PWM; // 选用PWM模式
x.T16Nx_PREMAT = 0x01; /* 预分频比1:1 */ T16Nx_BaseInit(T16N0, &x); /* 配置T16N0通道1输出 */ y.T16Nx_MOE0 = Disable; y.T16Nx_MOE1 = Enable; y.T16Nx_POL0 = POSITIVE; //在串口发送的时候,正极性代表发送的数据与接受的数据相同,负极性代表与发送的数据相反,在这么不知道有没有作用
y.T16Nx_POL1 = POSITIVE; y.T16Nx_PWMMODE = T16Nx_PWMMode_INDEP; //选择独立模式
y.PWMDZE = Disable; // PWM互补模式死区使能
y.REGBUFEN = Enable; //缓冲寄存器使能 (REGBUFEN目前不知道干什么用的)
T16Nx_PMWOutInit(T16N0, &y); /* 配置T16N0 通道1输出 */ /*MAT2 MAT3 通道的中断配置*/ //匹配寄存器值匹配后的工作模式,计数到以后: 继续计数不产生中断
T16Nx_MAT2ITConfig(T16N0, T16Nx_Go_No); //匹配寄存器值匹配后的工作模式,清零并重新计数,产生中断
T16Nx_MAT3ITConfig(T16N0, T16Nx_Clr_Int);
/*MAT2 MAT3 匹配后的输出电平高低*/ T16Nx_MAT2Out1Config(T16N0, T16Nx_Out_Low); //匹配后输出端口的模式,输出高还是低
T16Nx_MAT3Out1Config(T16N0, T16Nx_Out_High); //匹配后输出端口的模式,输出高还是低
//以上是设置模式,输出高低电平
T16Nx_SetCNT1(T16N0, 0); //设定计数器的初始值
T16Nx_SetMAT2(T16N0, 0); //设置匹配寄存器的数值
T16Nx_SetMAT3(T16N0, 0); //设置匹配寄存器的数值
//设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
T16Nx_SetTOP1(T16N0, 0); //以上是设置占空比
/* 配置输出管脚 */ GPIO_InitSettingType initset;
initset.Signal = GPIO_Pin_Signal_Digital; //数字
initset.Dir = GPIO_Direction_Output; //输出模式
initset.Func = GPIO_Reuse_Func2; //复用到T16N0_1功能
initset.ODE = GPIO_ODE_Output_Disable; //开漏使能
initset.DS = GPIO_DS_Output_Normal; //普通电流模式
initset.PUE = GPIO_PUE_Input_Enable; //弱上拉使能
initset.PDE = GPIO_PDE_Input_Disable; //弱下拉禁止
/* 配置PA4为T16N0输出通道1 */ GPIO_Init(GPIO_Pin_A4, &initset); T16Nx_Enable(T16N0); return; }
void set_pwm_t16_pa4(uint32_t freqhz, double duty) { double top_double = calculate_top(freqhz); //根据需要的频率计算出TOP(自动重装载值)
uint16_t top = (uint16_t)top_double; uint16_t Mat2 = (uint16_t)top_double * (duty / 100.0); uint16_t Mat3 = top; if (Mat2 >= top) Mat2 = top - 1; // printf("Mat2:%d\r\n", Mat2);
// printf("Mat3:%d\r\n", Mat3);
// printf("top:%d\r\n", top);
T16Nx_SetCNT1(T16N0, 0); //设定计数器的初始值
T16Nx_SetMAT2(T16N0, Mat2); //设置匹配寄存器的数值
T16Nx_SetMAT3(T16N0, Mat3); //设置匹配寄存器的数值
//设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
T16Nx_SetTOP1(T16N0, top); //以上是设置占空比
}
//######################################################
/**
* @brief 设置pwm的周期占空比 * * @param frequency * @param duty */
/**
* * 频率变化: * * * * 占空比变化: * 20->0 * 0->20 * 0->10 * * 有效时间逐渐增加,周期最大,有效时间不变,周期变小,频率变大 * * * * 周期变大,有效时间不变,周期变到最大,有效时间逐渐减小 * * * 1. 先变化到周期,如果周期时间大于占空比,则先变化到占空比 * 2. 再变化频率 * */
uint32_t s_target_frequencyhz; uint32_t s_now_frequencyhz;
uint32_t s_target_duty; uint32_t s_now_duty;
/**
* @brief * * @param freq * @param us */
// static uint32_t get_duty_by_freq_and_valid_time(uint32_t freq, uint32_t us) {
// uint32_t period = 1000000 / freq;
// uint32_t duty = us * 100 / period;
// return duty;
// }
// static uint32_t get_pwm_pulse_width_us_by_duty(uint32_t freq, uint32_t duty) {
// uint32_t period = 1000000 / freq;
// uint32_t pwm_pulse_width_us = period * duty / 100;
// return pwm_pulse_width_us;
// }
double get_duty(double now_duty, double target_duty, double increment_count) { if (now_duty > target_duty) { now_duty -= (now_duty - target_duty) / increment_count; //(now_duty-target_duty)/increment_count每次的增量
} else if (now_duty < target_duty) { now_duty += (target_duty - now_duty) / increment_count; } return now_duty; } void set_pwm_modbul_freq_duty(uint32_t frequencyhz, uint32_t duty) { static uint32_t now_frequencyhz; static double now_duty; static uint32_t pwm_pulse_width_us; uint32_t increment_conut; //从现在的频率到目标频率每次增加PWM_CHANGE_STEP_FREQ,还需要增加多少次
target_frequencyhz = frequencyhz; target_duty = duty; if (now_frequencyhz == target_frequencyhz) { if (now_duty != target_duty) { now_duty = target_duty; set_pwm_t16_pa4(now_frequencyhz, now_duty); } if ((uint32_t)now_duty == target_duty) { return; } } // pwm_pulse_width_us = get_pwm_pulse_width_us_by_duty(target_frequencyhz, target_duty);
if (now_frequencyhz < target_frequencyhz) { now_frequencyhz = now_frequencyhz + PWM_CHANGE_STEP_FREQ; if (now_frequencyhz >= target_frequencyhz) { now_frequencyhz = target_frequencyhz; } increment_conut = (target_frequencyhz - now_frequencyhz) / PWM_CHANGE_STEP_FREQ; // now_duty = get_duty_by_freq_and_valid_time(now_frequencyhz, pwm_pulse_width_us);
now_duty = get_duty(now_duty, target_duty, increment_conut); set_pwm_t16_pa4(now_frequencyhz, now_duty); printf("%d,%lf\r\n", now_frequencyhz, now_duty); } else if (now_frequencyhz > target_frequencyhz) { now_frequencyhz = now_frequencyhz - PWM_CHANGE_STEP_FREQ; if (now_frequencyhz <= target_frequencyhz) { now_frequencyhz = target_frequencyhz; } // now_duty = get_duty_by_freq_and_valid_time(now_frequencyhz, pwm_pulse_width_us);
increment_conut = (now_frequencyhz - target_frequencyhz) / PWM_CHANGE_STEP_FREQ; now_duty = get_duty(now_duty, target_duty, increment_conut); set_pwm_t16_pa4(now_frequencyhz, now_duty); printf("%d,%lf\r\n", now_frequencyhz, now_duty); } }
// uint32_t get_next_value_on_step(uint32_t now, uint32_t target, uint32_t step) {
// }
// void pwm_module_stop() { set_pwm_modbul_freq_duty(MIN_PWM_FREQ, 0); }
// void pwm_schdule() {
// /**
// * @brief 当前频率的占空比的百分之一变化
// */
// //计算当前频率下的目标占空比
// uint32_t targetduty = 0;
// uint32_t targetduty1 = s_target_duty;
// uint32_t targetduty2 = (1.0 / s_target_frequencyhz) * (s_target_duty / 100.0) / (1.0 / s_now_frequencyhz) * 100;
// targetduty = targetduty1 < targetduty2 ? targetduty1 : targetduty2;
// if (targetduty != s_now_duty) {
// set_pwm_t16_pa4(s_now_frequencyhz, targetduty);
// return;
// } else {
// //计算下一次设置的频率
// set_pwm_t16_pa4(s_now_frequencyhz, targetduty);
// }
// if (s_target_frequencyhz > s_now_frequencyhz) {
// s_now_frequencyhz += 1000;
// }
// }
//######################################################
//# c语言的理解
//# static , 字节长度 ,堆,栈,变量分布,
//# 操作系统
//# 线程,进程,信号量
//#
//#
|