/* os shim includes */ #include "os_types.h" #include "dbg_io.h" #include "iot_io.h" #include "gpio_mtx.h" #include "pwm.h" #include "cpu.h" void delay_sometime(uint32_t times) { uint32_t loop = 0; while (loop++ < times) { __asm volatile ("nop\n"); } } void register_print_by_addr(uint32_t addr, int num) { volatile uint32_t *p_addr = (volatile uint32_t *)addr; int i; for (i = 0; i < num; i++) { iot_printf("%08x,", *p_addr); p_addr ++; } iot_printf("\r\n"); } /* PWM 模块同步使用,PWM0为主,PWM1和PWM2 被PWM0同步,相位关系由pwm_tb_phase_set 控制 */ void pwm_main2(void) { uint8_t ch = PWM_CHANNEL_0; dbg_uart_init(); pwm_tbclk_sync(ch, false); // 8 7 pwm_gpio_config(ch, 26, 27); pwm_tbclk_ctrl(ch, true); // 使能PWM0 的时钟 pwm_tb_phase_set(ch, 0); pwm_tbctl_set(ch, TB_DISABLE, TB_SHADOW, TB_SYNC_CNT_ZERO,99); //pwm waveform period pwm_tb_period_set(ch, 9999); //load from shadow select mode pwm_cmpctl_set(ch, CC_CTR_ZERO, CC_CTR_ZERO, CC_NO_SHADOW, CC_NO_SHADOW); //action when counter equals zero or CMPA register pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_cmpa_cmpb_set(ch, 3000, 6000); pwm_cnt_mode_set(ch, TB_COUNT_UP); pwm_db_inmode_set(ch, DB_INMODE_PWMA_RAW, DB_INMODE_PWMB_RAW); pwm_db_polsel_set(ch, DB_POLSE_NORMAL, DB_POLSE_INVERTED); //A不反相,B反相 //pwm_db_outmode_set(ch, DB_OUTMODE_BYPASS, DB_OUTMODE_DELAYED );//A不产生死区,B产生 //pwm_db_outmode_set(ch, DB_OUTMODE_BYPASS, DB_OUTMODE_BYPASS ); //都不产生死区 pwm_db_rising_delay_set(ch, 1000); pwm_db_falling_delay_set(ch, 1000); //----------------------------------------------------------------------------- ch = PWM_CHANNEL_1; // 10 9 pwm_gpio_config(ch, 28, 29); pwm_tbclk_ctrl(ch, true); // 使能PWM1 的时钟 pwm_tb_phase_set(ch, 3333); pwm_tbctl_set(ch, TB_ENABLE, TB_SHADOW, TB_SYNC_PWM,99); //pwm waveform period pwm_tb_period_set(ch, 9999); //load from shadow select mode pwm_cmpctl_set(ch, CC_CTR_ZERO, CC_CTR_ZERO, CC_NO_SHADOW, CC_NO_SHADOW); //action when counter equals zero or CMPA register pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_cmpa_cmpb_set(ch, 3000, 6000); pwm_cnt_mode_set(ch, TB_COUNT_UP); pwm_db_inmode_set(ch, DB_INMODE_PWMA_RAW, DB_INMODE_PWMB_RAW); pwm_db_polsel_set(ch, DB_POLSE_NORMAL, DB_POLSE_INVERTED); pwm_db_outmode_set(ch, DB_OUTMODE_BYPASS, DB_OUTMODE_BYPASS ); pwm_db_rising_delay_set(ch, 1000); pwm_db_falling_delay_set(ch, 1000); //------------------------------------------------------------------------- ch = PWM_CHANNEL_2; // 19 38 pwm_gpio_config(ch, 9, 12); pwm_tbclk_ctrl(ch, true); // 使能PWM2 的时钟 pwm_tb_phase_set(ch, 6666); pwm_tbctl_set(ch, TB_ENABLE, TB_SHADOW, TB_SYNC_PWM,99); //pwm waveform period pwm_tb_period_set(ch, 9999); //load from shadow select mode pwm_cmpctl_set(ch, CC_CTR_ZERO, CC_CTR_ZERO, CC_NO_SHADOW, CC_NO_SHADOW); //action when counter equals zero or CMPA register pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_cmpa_cmpb_set(ch, 3000, 6000); pwm_cnt_mode_set(ch, TB_COUNT_UP); //选择延迟输入信号 pwm_db_inmode_set(ch, DB_INMODE_PWMB_RAW, DB_INMODE_PWMB_RAW); pwm_db_polsel_set(ch, DB_POLSE_NORMAL, DB_POLSE_NORMAL); pwm_db_outmode_set(ch, DB_OUTMODE_BYPASS, DB_OUTMODE_BYPASS ); pwm_db_rising_delay_set(ch, 100); pwm_db_falling_delay_set(ch, 200); //------------------------------------------------------------------------- pwm_tbclk_sync(ch, true); while (1) { delay_sometime(1000000); delay_sometime(1000000); delay_sometime(1000000); delay_sometime(1000000); delay_sometime(1000000); } } //PWM 模块输出两路占空比可以独立调节的PWM波形,需要注意的点是在不同的 //占空比组合下需要对AQ的特别设置 void pwm_main3(void) { uint8_t ch = PWM_CHANNEL_0; dbg_uart_init(); pwm_tbclk_sync(ch, false); // 8 7 pwm_gpio_config(ch, 26, 27); pwm_tbclk_ctrl(ch, true); // 使能PWM0 的时钟 pwm_tb_phase_set(ch, 0); pwm_tbctl_set(ch, TB_DISABLE, TB_SHADOW, TB_SYNC_CNT_ZERO, 99); //pwm waveform period pwm_tb_period_set(ch, 9999); //load from shadow select mode //注意这里必须都设为CC_CTR_PRD,如果为CC_CTR_ZERO 输出的波形不对, //在B的占空比为0时,A会少一个脉冲 pwm_cmpctl_set(ch, CC_CTR_PRD, CC_CTR_PRD, CC_SHADOW, CC_SHADOW); //action when counter equals zero or CMPA register pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_cnt_mode_set(ch, TB_COUNT_UP); // 独立输出PWM 0-100都可以,给duty_a和duty_b初值分别赋: // 0 0 A B输出相同占空比的PWM波形 // 0 100 A 为0时B不为0 // 100 0 B 为0时A不为0 // int duty_a = 0; int duty_b = 10000; pwm_cmpa_cmpb_set(ch, duty_a, duty_b); pwm_tbclk_sync(ch, true); while (1) { //因为cntb_up的优先级高于cnta_up,所以最终起作用的是b,故应改变b的配置 if (duty_a == duty_b) { pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); } else if (duty_a == 0) { pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); } else if (duty_b == 0) { pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_SET, AQ_NOTHING); pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); } else { pwm_aqctlb_set(ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_aqctla_set(ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); } pwm_cmpa_cmpb_set(ch, duty_a, duty_b); duty_a += 100; if (duty_a > 10000) duty_a = 0; duty_b += 100; if (duty_b > 10000) duty_b = 0; delay_sometime(10000); } } int g_duty_a = 100; int g_duty_b = 200; uint8_t g_ch = PWM_CHANNEL_3; //每个周期都改变占空比 uint32_t interrupt_cb(void) { g_duty_a += 100; if (g_duty_a > 10000) { g_duty_a = 100; } g_duty_b += 100; if (g_duty_b > 10000) { g_duty_b = 200; } pwm_cmpa_cmpb_set(g_ch, g_duty_a, g_duty_b); return 0; } // 中断测试 void pwm_main4(void) { uint32_t cpu_id = cpu_get_mhartid(); dbg_uart_init(); iot_interrupt_init(cpu_id); pwm_tbclk_sync(g_ch, false); // 8 7 pwm_gpio_config_with_isr(g_ch, 26, 27, interrupt_cb); pwm_tbclk_ctrl(g_ch, true); // 使能PWM 的时钟 pwm_tb_phase_set(g_ch, 0); pwm_tbctl_set(g_ch, TB_DISABLE, TB_SHADOW, TB_SYNC_CNT_ZERO,99); //pwm waveform period pwm_tb_period_set(g_ch, 9999); //load from shadow select mode //注意:若A或B 的ld mode被配置为 CC_CTR_FREEZE 则B的占空比保持着不再变化, //却决于原来的状态,若是上电第一次运行,则B保持全低或者全高 pwm_cmpctl_set(g_ch, CC_CTR_PRD, CC_CTR_PRD, CC_SHADOW, CC_SHADOW); //action when counter equals zero or CMPA register pwm_aqctlb_set(g_ch, AQ_SET, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING); pwm_aqctla_set(g_ch, AQ_SET, AQ_NOTHING, AQ_CLEAR, AQ_NOTHING, AQ_NOTHING, AQ_NOTHING); pwm_cnt_mode_set(g_ch, TB_COUNT_UP); //pwm_interrupt_init(g_ch); pwm_cmpa_cmpb_set(g_ch, g_duty_a, g_duty_b); pwm_tbclk_sync(g_ch, true); while (1); } //输出 h 和 l输出互补的pwm 波形 void pwm_main5() { uint8_t ch = PWM_CHANNEL_0; float duty = 0.01; dbg_uart_init(); pwm_gpio_config(ch, 58, 59); pwm_init(ch); pwm_start(ch); pwm_set_duty(ch, 50 * 100); while (1) { //pwm_set_duty(ch, duty * 100); duty += 0.01; if (duty > 100) { duty = 0.01; } delay_sometime(1000); } } #ifdef __GNUC__ int main(void) { pwm_main5(); return 0; } #endif // __GCC__