340 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			340 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /* 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__
 | |||
|  | 
 |