#include "pwm.h" #define CLCK 48 void t16_pa4_init(void) { // 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; } //###################################################### static double calculate_top(double target_frequency) { int clck = 0; int target_frequency_hz = 0; int top = 0; clck = CLCK * 1000 * 1000; target_frequency_hz = (int)target_frequency * 1000; // printf("target_frequency_hz%d\n", target_frequency_hz); top = clck / target_frequency_hz; // printf("top%d\t\n", top); return top; } static double calculate_MAT2(double top, double duty) { double percentage_duty = 0; double Mat2 = 0; percentage_duty = duty / 100; Mat2 = top * percentage_duty; return Mat2; } /** * @brief 设置pwm的周期占空比 * * @param frequency * @param duty */ void set_pwm_modbul_freq_duty(uint32_t frequency, uint32_t duty) { double top = 0; double Mat2 = 0; if (frequency > CLCK * 1000) { printf("out of range\n"); return; } top = calculate_top(frequency); //根据需要的频率计算出TOP(自动重装载值) if (top == 0) { return; } Mat2 = calculate_MAT2(top, duty); printf("top:\t%2.lf\n", top); printf("MAT2:\t%2.lf\n", Mat2); printf("MAT3:\t%2.lf\n", top); T16Nx_Disable(T16N0); t16_pa4_init(); T16Nx_SetMAT2(T16N0, Mat2); if (duty == 100) { T16Nx_SetMAT3(T16N0, top - 1); } else { T16Nx_SetMAT3(T16N0, top); } T16Nx_SetTOP1(T16N0, top); } //######################################################