Files
kunlun/dtest/dtest3/kl3_pwm_test/kl3_pwm_test.c
2024-09-28 14:24:04 +08:00

340 lines
9.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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__