X
首页
技术
模拟电子
单片机
半导体
电源管理
嵌入式
传感器
最能打国产芯
应用
汽车电子
工业控制
家用电子
手机便携
安防电子
医疗电子
网络通信
测试测量
物联网
最能打国产芯
大学堂
首页
直播
专题
TI 培训
论坛
汽车电子
国产芯片
电机驱动控制
电源技术
单片机
模拟电子
PCB设计
电子竞赛
DIY/开源
嵌入式系统
医疗电子
颁奖专区
【厂商专区】
【电子技术】
【创意与实践】
【行业应用】
【休息一下】
最能打国产芯
活动中心
直播
发现活动
颁奖区
电子头条
参考设计
下载中心
分类资源
文集
排行榜
电路图
Datasheet
最能打国产芯
国产芯片交流
[MCU] 先楫半导体HPM5361EVK--pwm
chejia12
2023-12-17 17:40
楼主
# pwm控制器 这里需要特别注意寄存器的影子寄存器的生效时机,我当初就是看不懂 ```c //配置选择影子寄存器生效时机 //pwm_load_cmp_shadow_on_match ( PWM, cmp_index + 2, &cmp_config[1] ); ``` 1.支持2个pwm定时器,每个pwm支持28位计数器,支持24个通道 **信号连接如下**: 1. 通道0-7输出pwm,连接到IO上 2. 通道8-23输出**连接到电机控制单元的互联管理器** 3. 输入捕获通道0-7来自IO 4. 输入捕获的8-23**来自电机控制单元的互联管理器** 5. 同步输入**来自电机控制单元的互联管理器** 6. 强制输出的使能输入**来自电机控制单元的互联管理器** 7. 强制输出的影子寄存器的生效触发 **来自电机控制单元的互联管理器** 8. 外部故障来自IO 9. 内部故障输入**来自电机控制单元的互联管理器**** ## 主要特性 - **28 (24 +4) 位**分辨率计数器,支持**向上**计数模式 - 支持计数器**同步** - 多达 24 个比较器,支持用作**输出比较,或者输入捕获** - 多达 24 个通道,其中通道 0∼7 可用于 PWM 输出 - 支持 **8 路独立**或者 4 **对互补** PWM 输出 - 互补 PWM 支持**死区插入**,支持独立配置**双侧**死区宽度 - 支持把 PWM 输出**强制设置为指定状**态 - 支持故障保护输入,在出错时(如故障保护输入时),**单独配置每个 PWM 输出通道的状态** - 支持为每个输出通道**灵活地分配数目不等的比较器**,灵活控制输出信号,生成例如边沿对齐 PWM、左右不对称的中央对齐 PWM 以及更复杂的输出信号 - 支持生成各类 DMA 请求和中断请求 - 部分寄存器配有影子寄存器,支持灵活的寄存器新值**更新/生效时机** ## **器时间基准** **时间基准模块的作用是决定 PWM 定时器运行的时间和周期** - **计数器**,计数器包括**计数器和扩展计数**两部分,计数器 24 位,扩展 4 位。可以合并成 28 位计数器使用 - **起始寄存器**,可以设置计数器起始值和扩展起始值 - **重载寄存器**,可以设置计数器重载值和扩展重载值
计数器使能 (GCR[CEN] 位置 1) 以后,总是从起始值开始计数,当计时器的值(CNT)计数至重载值(RLD)后,重载标志**RLDF**位置 1,此时,扩展计数器值 +1,计数器的值恢复到起始值(STA)。当扩展计数器值(XCNT)也计数到扩展重载值(**XRLD**)后,重载标志XRLDF位置 1,扩展计数器恢复到起始值 ### 同步 1. 需要打开 2. 同步触发输入可以**重置计数器到起始值** **半重载标志位HALFRLDF** ## **PWM** **生成** 1. PWM 生成需要**配合使用比较器和通道,主要功能是以通道为单位,利用比较器组合生成输出参考信号** 2. PWM 生成模块包括 24 个比较器和 24 个输出通道 3. 中通道 0 到通道 7 是 PWM 输出通道,通道输出 CH0REF ∼ CH7REF **连接到 PWM 控制逻辑**,如互补控制,死区生成,故障保护等模块。最终输出信号 OUT0∼OUT7 到芯片的管脚上 4. 通道 8 及之后的通道是通用输出通道,这些通道的输出参考信号**不经过 PWM 控制逻辑**,也可以输出信号供内外部使用
5. PWM 定时器的 24 个比较器,当它们用于 PWM 生成时,**需要配置为输出比较模式** 6. 比较器寄存器还包含 **4 位为小数比较位** 7. 用户可以把一个或者多个连续的比较器分配给某个通道,实现灵活复杂的输出,用户通过设置 CHCFGx [CMPSELBEG] 位,选择分配给通道 x 的比较寄存器**起始序号**。通过设置 CHCFGx [CMPSELEND] 位,选择分配给通道 x的比较寄存器**末尾序号**。 8. 当计数器 CNT 计数达到比较器 CMPx 配置的CMP或者XCMP时,产生**匹配事件,此时 OCx 输出置逻辑 1**。当计数器 CNT 值到**达重载寄存器,发生重载事件,输出重置逻辑 0** 9. 通道 x 的输出参考信号 CHxREF,由分配给它的全部比较器输出 OC*BEG* ∼OC*END* **异或后得到**。 10. CMPHLF是**半周期比较位**,由 PWM 定时器时钟的下边沿实现,该位置 1,可以使**匹配事件的生成时间延后 1/2 时钟周期**。 11. CMPJIT是**抖动比较位**,由 4,8,16 个周期边沿抖动,平均后**实现精度达 1/4,1/8 和 1/16 时钟周期的延时效果**。 12. 13. ### **PWM** **输出控制概述** PWM 输出通道(通道 0∼7)的参考信号(CH0REF∼CH7REF)经过后续的互补控制,死区插入,取反控制,强制输出,故障保护后,形成输出信号(OUT0∼OUT7)到 IO
**互补输出**:偶数序号的 PWM 通道配置会生效,奇数序号的 PWM 通道输出为偶数通道的输出取反 **死区控制**: 1. 在 2 路互补的参考信号上插入的不同的延时 2. 必须同时配置成对的通道 x 和通道 x+1寄存器才能正确地生成死区。 3. 配置死区长度的单位是 0.5 个 PWM 定时器时钟周期 **输出极性配置** ### **强制输出控制** 1. **允许用户把参考信号配置成指定的状态** 2. **触发方式**:硬件触发还是由软件触发 3. **强制输出生效时机**:可以选择输出生效的时机。 4. 可以配置强制输出生效时通道 0∼7 输出的状态 ### **故障保护** 1. 选择外部故障输入信号是逻辑 1 生效,还是逻辑 0 生效。 2. 打开或者关闭 PWM 定时器的**外部故障**输入 3. ,打开或者关闭 PWM 定时器的**内部故障**输入 4. 一旦故障发生,那么在系统状态变化之前,PWM 输出都不会恢复。用户可以通过设置 PWMCFGx[FAULTRECTIME],选择 **PWM 恢复的时机**: 5. 用户可以选择打开一个或者多个乃至全部故障输入信号。在打开的故障输入中,**任意一个生效时,故障保护即有效。** ### 择比较器的工作模式 - 1’b0,输出比较模式,比较器可以被分配给通道,用作输出 - 1’b1,输入捕获模式,此时,比较器用来捕获输入信号的翻转,并在**翻转时保存计数器的值**(CNT 和XCNT)。 把比较器配置成输入捕获模式后,用户可以从寄存器 **CAPPOSx** 寄存器读取到 CMPx 在信号(INx)**上升沿**捕获到的计数器值;在 **CAPNEGx** 寄存器读取到 CMPx 在**下降沿**捕获到的计数器值。CAPPOSx 和 CAPNEGx 寄存器即会保存计数器寄存器的 24 位计数器(CNT)值,也会保存 4 位扩展计数器(XCNT)值 ### 三组寄存器支持**影子寄存器**: ● **计数器的起始寄存器 STA(包括 STA/XSTA)和重载寄存器 RLD**(包括 RLD/XRLD) ● 比较器 CMPx,当其在用作输出比较时 ● 控制寄存器中的 FRCMD[FRCMD] 位,即通道 0∼7(PWM 通道)的强制输出控制模式位 ### STA、RLD生效时机 1. 软件把 **SHLK [SHLK] 位置 1** 后生效,(SHLK [SHLK]是影子寄存器锁定位) 2. **实时生效**,在寄存器写之后,一个周期内生效 3. 定时器的某一个 CMP 发生匹配后生效,通过 **SHCR[CNTSHDWSEL] 选择一个比较器** 4. 影子寄存器重载触发输入 SHRLDSYNCI 上捕获到上升沿时 ### 比较寄存器cmp生效时机 1. 软件把 **SHLK [SHLK] 位置 1** 后生效 2. **实时生效**,在寄存器写之后,一个周期内生效 3. 定时器的某一个 CMP 发生匹配后生效,通过 **CMPCFGx[CMPSHDWUPT]**** 选择一个比较器** 4. 影子寄存器重载触发输入 SHRLDSYNCI 上捕获到上升沿时 ### 强制输出模式位的影子寄存器位生效 1. 软件把 **SHLK [SHLK] 位置 1** 后生效 2. **实时生效**,在寄存器写之后,一个周期内生效 3. 定时器的某一个 CMP 发生匹配后生效,通过 ** SHCR [FRCSHDWSEL] **** 选择一个比较器** 4. 影子寄存器重载触发输入 SHRLDSYNCI 上捕获到上升沿时 ## pwm 输入比较结构 ```c /** *
@brief
pwm compare config * */ typedef struct pwm_cmp_config { uint32_t cmp; /**< 比较器的值compare value */ bool enable_ex_cmp; /**< 比较器的扩展的值enable extended compare value */ #if PWM_SOC_HRPWM_SUPPORT bool enable_hrcmp; /**< enable high precision pwm 使能高分辨率比较*/ #endif uint8_t mode; /**< pwm输出或输入捕获选择 compare work mode: pwm_cmp_mode_output_compare or pwm_cmp_mode_input_capture */ uint8_t update_trigger; /**< 比较配置更新触发器 compare configuration update trigger */ uint8_t ex_cmp; /**< 扩展比较值 extended compare value */ uint8_t half_clock_cmp; /**< half clock compare value*/ uint8_t jitter_cmp; /**< 抖动比较值 jitter compare value */ #if PWM_SOC_HRPWM_SUPPORT uint8_t hrcmp; /**< high precision pwm */ #endif } pwm_cmp_config_t; ``` ### pwm影子寄存器生效时机 ```c /** * @brief update time of the shadow register * */ typedef enum pwm_register_update { pwm_shadow_register_update_on_shlk = 0, /**< 软件把 **SHLK [SHLK] 位置 1** 后生效 after software set shlk bit of shlk register*/ pwm_shadow_register_update_on_modify = 1, /**< **实时生效** immediately after the register being modified*/ pwm_shadow_register_update_on_hw_event = 2, /**< 定时器的某一个 CMP 发生匹配后生效 after hardware event assert*/ pwm_shadow_register_update_on_sh_synci = 3, /**< 重载触发输入 SHRLDSYNCI 上捕获到上升沿时 after SHSYNCI assert */ } pwm_shadow_register_update_trigger_t; ``` ### 故障后恢复PWM输出的时机 ````c /** * @brief select when to recover PWM output after fault 选择故障后恢复PWM输出的时机 * */ typedef enum pwm_fault_recovery_trigger { pwm_fault_recovery_immediately = 0, /**< 立即 immediately*/ pwm_fault_recovery_on_reload = 1, /**< 重新加载时 after pwm timer counter reload time*/ pwm_fault_recovery_on_hw_event = 2, /**< after hardware event assert*/ pwm_fault_recovery_on_fault_clear = 3, /**< 软件写故障位 after software write faultclr bit in GCR register*/ } pwm_fault_recovery_trigger_t; ```` ```c /** * @brief pwm config data * */ typedef struct pwm_config { #if PWM_SOC_HRPWM_SUPPORT bool hrpwm_update_mode; /**< 模式一或零,HR CMP更新定时 mode one or zero, HR CMP update timing */ #endif bool enable_output; /**< 使能pwm输出enable pwm output */ bool invert_output; /**< 互补pwm输出电平 invert pwm output level */ uint8_t update_trigger; /**< pwm config update trigger */ uint8_t fault_mode; /**< 故障模式fault mode */ uint8_t fault_recovery_trigger; /**< 故障恢复触发 fault recoverty trigger */ uint8_t force_source; /**< 故障源 fault source */ uint32_t dead_zone_in_half_cycle; /**< 半周期死区dead zone in half cycle*/ } pwm_config_t; ``` ### 配置一个通道的比较器 ```c /** * @brief setup waveform设置波形 * * @param[in] pwm_x PWM base address, HPM_PWMx(x=0..n) * @param[in] pwm_index pwm channel index pwm通道编号 (0..(PWM_SOC_PWM_MAX_COUNT-1)) * @param[in] pwm_config
@ref
pwm_config_t pwm配置结构体 * @param[in] cmp_start_index pwm cmp index 比较器的其实编号 (0..(PWM_SOC_PWM_MAX_COUNT-1)) * @param[in] cmp @ref pwm_cmp_config_t 比较器配置结构体开始指针 * @param[in] cmp_num cmp num 配置的比较器数量 (1..PWM_SOC_CMP_MAX_COUNT), cmp[cmp_num-1] must not overflow * @retval hpm_stat_t */ hpm_stat_t pwm_setup_waveform(PWM_Type *pwm_x, uint8_t pwm_index, pwm_config_t *pwm_config, uint8_t cmp_start_index, pwm_cmp_config_t *cmp, uint8_t cmp_num); ``` ## 测试实例 开发板原理图 根据原理图和引脚功能可知 PA26-->PWM2 PA27-->PWM3
### PWM2 PWM3 强制输出高低电平测试 ```c /* PWM2 PWM3 强制输出高低电平测试 */ void test_pwm_force_output ( void ) { //配置引脚复用 HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_PWM0_P_2; HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_PWM0_P_3; //强制输出时机控制--立即生效 pwm_config_force_cmd_timing ( PWM, pwm_force_immediately ); //打开强制输出 pwm_enable_pwm_sw_force_output ( PWM, 2 );//pa26-->PWM2 pwm_enable_pwm_sw_force_output ( PWM, 3 );//pa27--->PWM3 printf ( "Output high\n" ); //强制输出模式控制位 pwm_set_force_output ( PWM, PWM_FORCE_OUTPUT ( 2, pwm_output_1 ) | PWM_FORCE_OUTPUT ( 3, pwm_output_1 ) ); //软件强制输出 pwm_enable_sw_force ( PWM ); board_delay_ms ( 5000 ); printf ( "Output low\n" ); pwm_set_force_output ( PWM, PWM_FORCE_OUTPUT ( 2, pwm_output_0 ) | PWM_FORCE_OUTPUT ( 3, pwm_output_0 ) ); board_delay_ms ( 5000 ); pwm_disable_sw_force ( PWM ); //关闭强制输出 pwm_disable_pwm_sw_force_output ( PWM, 2 ); pwm_disable_pwm_sw_force_output ( PWM, 3 ); } ``` ### 输出pwm波形 ````c void generate_edge_aligned_waveform ( void ) { uint8_t cmp_index = 0; uint32_t duty, duty_step; bool increase_duty_cycle = true; pwm_cmp_config_t cmp_config[2] = {0}; pwm_config_t pwm_config = {0}; //配置通道2和3的pin复用 HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_PWM0_P_2; HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_PWM0_P_3; //使能/关闭 PWM 定时器的计数器 pwm_stop_counter ( PWM ); reset_pwm_counter(); pwm_get_default_pwm_config ( PWM, &pwm_config ); pwm_config.enable_output = true; pwm_config.dead_zone_in_half_cycle = 0; pwm_config.invert_output = false; /* * reload and start counter */ pwm_set_reload ( PWM, 0, reload );//设置重载值 pwm_set_start_count ( PWM, 0, 0 );//启动定时器 /* * config cmp = RELOAD + 1 */ cmp_config[0].mode = pwm_cmp_mode_output_compare;//输出比较模式 cmp_config[0].cmp = reload + 1;//设置比较直 cmp_config[0].update_trigger = pwm_shadow_register_update_on_hw_event;//影子寄存器更新时机 这里选择的是以某一个比较器的匹配事件作为生效时机 cmp_config[1].mode = pwm_cmp_mode_output_compare; cmp_config[1].cmp = reload; cmp_config[1].update_trigger = pwm_shadow_register_update_on_modify;//立即生效 /* * config pwm as output driven by cmp 配置通道的pwm数据和匹配一个比较器 设置波形 */ if ( status_success != pwm_setup_waveform ( PWM, 2, &pwm_config, cmp_index, &cmp_config[0], 1 ) ) { printf ( "failed to setup waveform\n" ); while ( 1 ); } cmp_config[0].cmp = reload >> 1;//占空比位50 /* * config pwm as reference */ if ( status_success != pwm_setup_waveform ( PWM, 3, &pwm_config, cmp_index + 1, &cmp_config[0], 1 ) ) { printf ( "failed to setup waveform\n" ); while ( 1 ); } printf ( "............................\n" ); //配置比较器2的 的影子寄存器生效时机,这里选择的是以某一个比较器的匹配事件作为生效时机 pwm_load_cmp_shadow_on_match ( PWM, cmp_index + 2, &cmp_config[1] ); pwm_start_counter ( PWM ); pwm_issue_shadow_register_lock_event ( PWM ); duty_step = reload / 100; duty = reload / 100; increase_duty_cycle = true; for ( uint32_t i = 0; i < TEST_LOOP; i++ ) { if ( increase_duty_cycle ) { if ( ( duty + duty_step ) >= reload ) { increase_duty_cycle = false; continue; } duty += duty_step; } else { if ( duty <= duty_step ) { increase_duty_cycle = true; continue; } duty -= duty_step; } //调整占空比 pwm_update_raw_cmp_edge_aligned ( PWM, cmp_index, reload - duty ); board_delay_ms ( 100 ); } } ```` ### 立即生效的版本 ```c void generate_edge_aligned_waveform ( void ) { uint8_t cmp_index = 0; uint32_t duty, duty_step; bool increase_duty_cycle = true; pwm_cmp_config_t cmp_config[2] = {0}; pwm_config_t pwm_config = {0}; //配置通道2和3的pin复用 HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_PWM0_P_2; HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_PWM0_P_3; //使能/关闭 PWM 定时器的计数器 pwm_stop_counter ( PWM ); reset_pwm_counter(); pwm_get_default_pwm_config ( PWM, &pwm_config ); pwm_config.enable_output = true; pwm_config.dead_zone_in_half_cycle = 0; pwm_config.invert_output = false; /* * reload and start counter */ pwm_set_reload ( PWM, 0, reload );//设置重载值 pwm_set_start_count ( PWM, 0, 0 );//启动定时器 /* * config cmp = RELOAD + 1 */ cmp_config[0].mode = pwm_cmp_mode_output_compare;//输出比较模式 cmp_config[0].cmp = reload + 1;//设置比较直 cmp_config[0].update_trigger = pwm_shadow_register_update_on_modify;//影子寄存器更新时机 硬件事件后asser cmp_config[1].mode = pwm_cmp_mode_output_compare; cmp_config[1].cmp = reload; cmp_config[1].update_trigger = pwm_shadow_register_update_on_modify; /* * config pwm as output driven by cmp 配置通道的pwm数据和匹配一个比较器 设置波形 */ if ( status_success != pwm_setup_waveform ( PWM, 2, &pwm_config, cmp_index, &cmp_config[0], 1 ) ) { printf ( "failed to setup waveform\n" ); while ( 1 ); } cmp_config[0].cmp = reload >> 1;//占空比位50 /* * config pwm as reference */ if ( status_success != pwm_setup_waveform ( PWM, 3, &pwm_config, cmp_index + 1, &cmp_config[0], 1 ) ) { printf ( "failed to setup waveform\n" ); while ( 1 ); } printf ( "............................\n" ); //配置选择影子寄存器生效时机 //pwm_load_cmp_shadow_on_match ( PWM, cmp_index + 2, &cmp_config[1] ); pwm_start_counter ( PWM ); pwm_issue_shadow_register_lock_event ( PWM ); duty_step = reload / 100; duty = reload / 100; increase_duty_cycle = true; for ( uint32_t i = 0; i < TEST_LOOP; i++ ) { if ( increase_duty_cycle ) { if ( ( duty + duty_step ) >= reload ) { increase_duty_cycle = false; continue; } duty += duty_step; } else { if ( duty <= duty_step ) { increase_duty_cycle = true; continue; } duty -= duty_step; } pwm_update_raw_cmp_edge_aligned ( PWM, cmp_index, reload - duty ); board_delay_ms ( 100 ); } } ```
本帖最后由 chejia12 于 2023-12-17 21:35 编辑
点赞
回复评论 (1)
沙发
dmx_xx
你好,博主我有点问题关于影子寄存器的,已私信。
点赞
2023-12-18 16:39
最新活动
是德科技有奖直播 | 应对未来高速算力芯片的设计与测试挑战
免费申请 | 上百份MPS MIE模块,免费试用还有礼!
TI 有奖直播 | 使用基于 Arm 的 AM6xA 处理器设计智能化楼宇
Follow me第二季第3期来啦!与得捷一起解锁高性能开发板【EK-RA6M5】超能力!
报名直播赢【双肩包、京东卡、水杯】| 高可靠性IGBT的新选择——安世半导体650V IGBT
30套RV1106 Linux开发板(带摄像头),邀您动手挑战边缘AI~
随便看看
AD程序模拟量输入 求助
【求助】stm8l单片机无法设置FLASH的寄存器?
fpga的供电电源芯片
msp430FR2433如何降低功耗
手表修复计。。。
当爸当妈不容易,来晒一晒那些带娃副产品!
求低通滤波电路的截止频率和Q值的求解过程
来看看交互技术演绎的艺术
预约有礼:免费申请体验全新福禄克热像仪,前100名预约有礼
TMS320VC5509A 连接不上仿真器问题查找及归纳
高薪急聘高级硬件工程师
第一周的心得体会
收到Open1081板子,晒图
程序下不进去问题解决,,原因讨论分析..十万火急
急求高手编程指教
485
Keil ARM5 支持ARM7/9 CM系列器件了
【EEworld原创教程讨论】+ 后续的期待
0欧姆电阻的用途
usb 枚举?代码~~
电子工程世界版权所有
京B2-20211791
京ICP备10001474号-1
京公网安备 11010802033920号
回复
写回复
收藏
回复