一、硬件资源
1、4对互补PWM输出,可以一路PWM控制一个步进电机
2、计数器为32位
3、多样化故障保护
4、支持24个比较值,这些比较值可以用来生成不同占空比的PWM,也可以用来触发其他外设。灵活方便
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
二、调试问题
1、需要注意比较值0,1,2,3对应一组互补的PWM输出,映射时不能将2,3映射到PWM_B中,且0.1.2.3对应手册中的a.b.c.d.
2、不能使用pwmv2_enable_counter(),库函数来分别使能通道的主定时器,会造成主定时器有误差,导致发生的PWM不同步。需要改为
//同时开启pwm3路主计数器,并使能
HPM_PWM1->CNT_GLBCFG = PWMV2_CNT_GLBCFG_TIMER_ENABLE_SET(0x07UL) | PWMV2_CNT_GLBCFG_CNT_SW_START_SET(0x07UL);

三、调试代码
/*
PE08–PWM1_CH0
PE09–PWM1_CH1
PE10–PWM1_CH2
PE11–PWM1_CH3
PE12–PWM1_CH4
PE13–PWM1_CH5

配置6路互补输出pwm,为中心对称模式, 频率:20KHZ, 死区:250NS
main while()中占空比可调
比较值16配置为,PWM1输出信号0,(对应互联管理器的PWM1触发信号输入0),触发ADC采样
*/
ATTR_PLACE_AT_FAST_RAM uint32_t reload = 10000;
ATTR_PLACE_AT_FAST_RAM uint32_t dutyA = 4000;
ATTR_PLACE_AT_FAST_RAM uint32_t dutyB = 4000;
ATTR_PLACE_AT_FAST_RAM uint32_t dutyC = 4000;
void Bsp_Pwmv2Out_Init(void)
{
reload = 10000;
dutyA = 4000;
dutyB = 4000;
dutyC = 4000;

// 使能PWM1时钟
clock_add_to_group(clock_pwm1, 0);


//初始化IO口
HPM_IOC->PAD[IOC_PAD_PE08].FUNC_CTL = IOC_PE08_FUNC_CTL_PWM1_P_0;

HPM_IOC->PAD[IOC_PAD_PE09].FUNC_CTL = IOC_PE09_FUNC_CTL_PWM1_P_1;

HPM_IOC->PAD[IOC_PAD_PE10].FUNC_CTL = IOC_PE10_FUNC_CTL_PWM1_P_2;

HPM_IOC->PAD[IOC_PAD_PE11].FUNC_CTL = IOC_PE11_FUNC_CTL_PWM1_P_3;

HPM_IOC->PAD[IOC_PAD_PE12].FUNC_CTL = IOC_PE12_FUNC_CTL_PWM1_P_4;

HPM_IOC->PAD[IOC_PAD_PE13].FUNC_CTL = IOC_PE13_FUNC_CTL_PWM1_P_5;


//互补输出, 中心对称模式配置

//重置PWM配置
pwmv2_deinit(HPM_PWM1);

//解锁影子寄存器
HPM_PWM1->WORK_CTRL0 = PWM_UNLOCK_KEY;

 
/*
设置影子寄存器值
HPM_PWM1:PWM1结构体
PWMV2_SHADOW_INDEX(0) :获取影子寄存器0的索引
reload:影子寄存器设置值, PWM频率:20000:200MHZ/10000 = 20KHZ
0:高精度值, SHADOW_VAL:寄存器[31:8]整数周期  [7:0]高精度,现在只配置整数部分,先不需要高精度
false:(其中 Bit[7] 为半周期)设置为FALSE
*/
//周期值影子寄存器
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(0), reload, 0, false);


//第一对互补PWM影子寄存器 
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(1), reload, 0, false);
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(2), reload, 0, false);

//第二对互补PWM影子寄存器
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(3), reload, 0, false);
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(4), reload, 0, false);

//第三对互补PWM影子寄存器
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(5), reload, 0, false);
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(6), reload, 0, false);

// 配置影子寄存器0 作为PWM1_A互补通道的重载值的 计数缓存
pwmv2_counter_select_data_offset_from_shadow_value(HPM_PWM1, pwm_counter_0, PWMV2_SHADOW_INDEX(0));
//关闭Brust发波
//HPM_PWM1->CNT[counter].CFG3 ,低16位为1,持续输出PWM
pwmv2_counter_burst_disable(HPM_PWM1, pwm_counter_0);


// 配置影子寄存器0 作为PWM1_B互补通道的重载值的 计数缓存
pwmv2_counter_select_data_offset_from_shadow_value(HPM_PWM1, pwm_counter_1, PWMV2_SHADOW_INDEX(0));
//关闭Brust发波
//HPM_PWM1->CNT[counter].CFG3 ,低16位为1,持续输出PWM
pwmv2_counter_burst_disable(HPM_PWM1, pwm_counter_1);


// 配置影子寄存器0 作为PWM1_C互补通道的重载值的 计数缓存
pwmv2_counter_select_data_offset_from_shadow_value(HPM_PWM1, pwm_counter_2, PWMV2_SHADOW_INDEX(0));
//关闭Brust发波
//HPM_PWM1->CNT[counter].CFG3 ,低16位为1,持续输出PWM
pwmv2_counter_burst_disable(HPM_PWM1, pwm_counter_2);



//配置重载值更新条件:在计数器重载时更新
pwmv2_set_reload_update_time(HPM_PWM1, pwm_counter_0, pwm_reload_update_on_reload);
pwmv2_set_reload_update_time(HPM_PWM1, pwm_counter_1, pwm_reload_update_on_reload);
pwmv2_set_reload_update_time(HPM_PWM1, pwm_counter_2, pwm_reload_update_on_reload);

//比较寄存器0,1,2,3对应于PWM_A通道
/*
配置比较寄存器更新来源

HPM_PWM1:PWM1结构体
PWMV2_CMP_INDEX(0):比较值0索引
cmp_value_from_shadow_val:比较值来自于影子寄存器值
PWMV2_SHADOW_INDEX(1):当前影子寄存器和比较值关联
*/
//将比较值0,关联到影子寄存器1
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(0), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(1));
//将比较值1,关联到影子寄存器2
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(1), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(2));

//将比较值3,关联到影子寄存器4
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(4), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(3));
//将比较值4,关联到影子寄存器5
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(5), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(4));

//将比较值5,关联到影子寄存器8
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(8), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(5));
//将比较值6,关联到影子寄存器9
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(9), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(6));



//设置通道死区长度,单位:时钟周期,主频200MHZ---  50 *5 = 250ns
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_0, 50);
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_1, 50);
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_2, 50);
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_3, 50);
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_4, 50);
pwmv2_set_dead_area(HPM_PWM1, pwm_channel_5, 50);

//锁定影子寄存器
HPM_PWM1->WORK_CTRL1 |= PWMV2_WORK_CTRL1_SHADOW_LOCK_MASK;

/*
对于 PWM 通道 N=0/2/4/6:
0:选择 2 个比较点模式 (N2~N2+1)
1:选择 4 个比较点模式 (N2~N2+3),或选择 2 个比较点模式
(N2+2~N2+3)
对于 PWM 通道 N=1/3/5/7,可工作在成对模式,或 2 个比较点
(N2+2~N2+3) 模式。
注意:如果只使用通道 1357,需要将对应通道 0246 的该位置 1,
以正常输出使能(其他通道 0246 的相关配置可以不用配置)。
当选择 2 比较点或 4 比较点的模式时,均支持可跨周期,即比较
点的值可配置在 0 至 2T 之间。
当计数器的值在 a 和 b 之间时,输出为 1;
如果 b<=a 则全部输出 0;
如果 b>=(T+a),则全部输出 1;
*/
//关闭4比较点模式,使能2比较点模式, pwm_channel_1工作在成对模式,不需要配置
pwmv2_disable_four_cmp(HPM_PWM1, pwm_channel_0);
pwmv2_disable_four_cmp(HPM_PWM1, pwm_channel_2);
pwmv2_disable_four_cmp(HPM_PWM1, pwm_channel_4);

//允许通道0,通道1输出
pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_0);
pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_1);

pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_2);
pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_3);

pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_4);
pwmv2_channel_enable_output(HPM_PWM1, pwm_channel_5);

//使能通道工作在成对模式
pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_0);
pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_1);

pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_2);
pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_3);

pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_4);
pwmv2_enable_pair_mode(HPM_PWM1, pwm_channel_5);

//同时开启pwm3路主计数器,并使能
HPM_PWM1->CNT_GLBCFG = PWMV2_CNT_GLBCFG_TIMER_ENABLE_SET(0x07UL) | PWMV2_CNT_GLBCFG_CNT_SW_START_SET(0x07UL);
#if 0
pwmv2_enable_counter(HPM_PWM1, pwm_counter_0);

pwmv2_enable_counter(HPM_PWM1, pwm_counter_1);

pwmv2_enable_counter(HPM_PWM1, pwm_counter_2);

//使能PWM输出
pwmv2_start_pwm_output(HPM_PWM1, pwm_counter_0);

pwmv2_start_pwm_output(HPM_PWM1, pwm_counter_1);

pwmv2_start_pwm_output(HPM_PWM1, pwm_counter_2);

#endif

//将比较值16,关联到影子寄存器7,作为触发输出信号(TRGM输入信号)使用--触发ADC采样
pwmv2_select_cmp_source(HPM_PWM1, PWMV2_CMP_INDEX(16), cmp_value_from_shadow_val, PWMV2_SHADOW_INDEX(7));
//设置ADC触发 影子寄存器7,初始化值为 PWM周期的一半,也就是PWM中心的触发
pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(7), reload >> 1, 0, false);

//从 24 个比较器中,选择一个作为此触发输出通道的比较点,当计数器到达比较点后,触发输出为 1,并在计数器到达重载值后输出 0
//设置比较器16,作为PWM触发输出信号0,至TRGM的输入
pwmv2_set_trigout_cmp_index(HPM_PWM1, 0, 16);

}
int main(void)
{
#if 1
uint32_t cpu0_freq = clock_get_frequency(clock_cpu0);
if (cpu0_freq == PLLCTL_SOC_PLL_REFCLK_FREQ) {
/* Configure the External OSC ramp-up time: ~9ms */
// pllctlv2_xtal_set_rampup_time(HPM_PLLCTLV2, 32ul * 1000ul * 9u);

    /* select clock setting preset1 */
    sysctl_clock_set_preset(HPM_SYSCTL, 2);
}
/* Add Clocks to group 0 */
clock_add_to_group(clock_cpu0, 0);
clock_add_to_group(clock_mchtmr0, 0);
clock_add_to_group(clock_ahb0, 0);
clock_add_to_group(clock_axif, 0);
clock_add_to_group(clock_axis, 0);
clock_add_to_group(clock_axic, 0);
clock_add_to_group(clock_axin, 0);
clock_add_to_group(clock_rom0, 0);
clock_add_to_group(clock_xpi0, 0);
clock_add_to_group(clock_lmm0, 0);
clock_add_to_group(clock_lmm1, 0);
clock_add_to_group(clock_ram0, 0);
clock_add_to_group(clock_ram1, 0);
clock_add_to_group(clock_hdma, 0);
clock_add_to_group(clock_xdma, 0);
clock_add_to_group(clock_gpio, 0);
clock_add_to_group(clock_ptpc, 0);
/* Motor Related */
clock_add_to_group(clock_qei0, 0);
clock_add_to_group(clock_qei1, 0);
clock_add_to_group(clock_qei2, 0);
clock_add_to_group(clock_qei3, 0);
clock_add_to_group(clock_qeo0, 0);
clock_add_to_group(clock_qeo1, 0);
clock_add_to_group(clock_qeo2, 0);
clock_add_to_group(clock_qeo3, 0);
clock_add_to_group(clock_pwm0, 0);
clock_add_to_group(clock_pwm1, 0);
clock_add_to_group(clock_pwm2, 0);
clock_add_to_group(clock_pwm3, 0);
clock_add_to_group(clock_rdc0, 0);
clock_add_to_group(clock_rdc1, 0);
clock_add_to_group(clock_plb0, 0);
clock_add_to_group(clock_sei0, 0);
clock_add_to_group(clock_mtg0, 0);
clock_add_to_group(clock_mtg1, 0);
clock_add_to_group(clock_vsc0, 0);
clock_add_to_group(clock_vsc1, 0);
clock_add_to_group(clock_clc0, 0);
clock_add_to_group(clock_clc1, 0);
clock_add_to_group(clock_emds, 0);
/* Connect Group0 to CPU0 */
clock_connect_group_to_cpu(0, 0);

/* Add the CPU1 clock to Group1 */
clock_add_to_group(clock_cpu1, 1);
clock_add_to_group(clock_mchtmr1, 1);
/* Connect Group1 to CPU1 */
clock_connect_group_to_cpu(1, 1);

/* Bump up DCDC voltage to 1275mv */

// pcfg_dcdc_set_voltage(HPM_PCFG, 1275);
// pcfg_dcdc_switch_to_dcm_mode(HPM_PCFG);

/* Set CPU clock to 600MHz */
clock_set_source_divider(clock_cpu0, clk_src_pll0_clk0, 1);
clock_set_source_divider(clock_cpu1, clk_src_pll0_clk0, 1);

/* Configure mchtmr to 24MHz */
clock_set_source_divider(clock_mchtmr0, clk_src_osc24m, 1);
clock_set_source_divider(clock_mchtmr1, clk_src_osc24m, 1);

clock_update_core_clock();
#endif


aa = 10;
//开启机器定时器0时钟
clock_add_to_group(clock_mchtmr0, 0);
//机器定时器时钟源选择
clock_set_source_divider(clock_mchtmr0, clk_src_osc24m, 1);


BSP_GPIO_Init();
BSP_UART_Init();
BSP_QEIV2_ABZInit();
Bsp_Pwmv2Out_Init();
Bsp_ADC16_Init();

while (1)
{
	aa++;

	//解锁影子寄存器
	HPM_PWM1->WORK_CTRL0 = PWM_UNLOCK_KEY;

	//PWM1_A
	//设置比较点a
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(1), (reload - dutyA) >> 1, 0, false);
	//设置比较点b
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(2), (reload + dutyA) >> 1, 0, false);

	//PWM1_B
	//设置比较点a
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(3), (reload - dutyB) >> 1, 0, false);
	//设置比较点b
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(4), (reload + dutyB) >> 1, 0, false);



	//PWM1_C
	//设置比较点a
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(5), (reload - dutyC) >> 1, 0, false);
	//设置比较点b
	pwmv2_set_shadow_val(HPM_PWM1, PWMV2_SHADOW_INDEX(6), (reload + dutyC) >> 1, 0, false);

	//锁定影子寄存器
	HPM_PWM1->WORK_CTRL1 |= PWMV2_WORK_CTRL1_SHADOW_LOCK_MASK;

	clock_cpu_delay_ms(1000);

}

}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐