找回密码
 立即注册
查看: 103|回复: 8

PWMA B模块会资源互斥么

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 2025-10-19 15:47:16 | 显示全部楼层 |阅读模式

// 方案002
// 头文件
#include    "STC8Hxxx.h"


// 引脚定义


// 宏定义
#define MAIN_Fosc   40000000UL      // 40MHz


// 声明
// 数组
// 函数
void u32_to_ascii(u32 v);                           // 打印32位整数(去除前导0)
void u16_to_ascii(u16 j);                           // 将数据转成十进制文本并从串口1发送
void ReturnValue(void);                             // 从串口1返回周期和高电平时间
void PWMB_config(void);                             // PWM配置函数
void SetTimer2Baudraye(u16 dat);                    // 设置Timer2做波特率发生器
void UART1_config(u32 brt, u8 timer, u8 io);        // UART1初始化函数
void UART1_TxByte(u8 dat);                          // 串口1查询发送一个字节函数
void PrintString1(u8 *puts);                        // 串口1字符串打印函数
// 变量
bit B_TX1_Busy;                         // 发送忙标志
bit B_Capture2;                         // 波形已捕捉完成

u8  PWMB_ISR_En;                        // 每个通道可以单独允许中断处理, bit4:通道4, bit3:通道3, bit2:通道2, bit1:通道1.

u16 ccr3;                               // 中断使用的中间变量, 用户层不可见
u16 period2;                            // 周期
u16 PulseHigh2;                         // 高电平时间, 占空比 = PulseHigh /period  * 100%


// 函数模块
// 打印32位整数(去除前导0)
void u32_to_ascii(u32 v)
{
    char buf[11];
    int i = 10;
    buf[i--] = 0;
    if(v == 0){ UART1_TxByte('0'); return; }
    while(v && i >= 0){ buf[i--] = (v%10)+'0'; v/=10; }
    for(i=i+1; buf!=0; i++) UART1_TxByte(buf);
}

// 将数据转成十进制文本并从串口1发送
void u16_to_ascii(u16 j)
{
    UART1_TxByte(j/10000+'0');
    UART1_TxByte((j%10000)/1000+'0');
    UART1_TxByte((j%1000)/100+'0');
    UART1_TxByte((j%100)/10+'0');
    UART1_TxByte( j%10+'0');
}

// 从串口1返回周期和高电平时间
void ReturnValue(void)
{
    unsigned long psc,freq,duty_x10;

    PrintString1("Period_count=");
    u16_to_ascii(period2);
    PrintString1("  High_count=");
    u16_to_ascii(PulseHigh2);

    // 预分频值
    psc = (unsigned long)PWMB_PSCR + 1UL;                                           // 预分频值


    if(period2==0)
    {
        PrintString1("  Freq=0Hz  Duty=0.0%\r\n");
        return;
    }


    // 频率占空比计算
    freq = (unsigned long)MAIN_Fosc / ((unsigned long)period2 * psc);               // 频率Hz
    duty_x10 = ((unsigned long)PulseHigh2 * 1000UL) / period2;                      // 占空比×10


    // 显示格式分配
    if(freq >= 1000)                    
    {
        unsigned long freq_khz_int = freq / 1000;
        unsigned long freq_khz_dec = (freq % 1000) / 100;
        PrintString1("  Freq=");
        u32_to_ascii(freq_khz_int);
        UART1_TxByte('.');
        UART1_TxByte('0'+(unsigned char)freq_khz_dec);
        PrintString1("kHz");
    }
    else
    {
        PrintString1("  Freq=");
        u32_to_ascii(freq);
        PrintString1("Hz");
    }

    UART1_TxByte(' ');
    PrintString1("Duty=");
    u32_to_ascii(duty_x10/10);
    UART1_TxByte('.');
    UART1_TxByte('0'+(unsigned char)(duty_x10%10));
    UART1_TxByte('%');
    UART1_TxByte(0x0d);
    UART1_TxByte(0x0a);
}

// PWM配置函数
void PWMB_config(void)
{
    P_SW2 |= 0x80;                                                                  // SFR enable   

    PWMB_CCER1  = 0;
    PWMB_CCER2  = 0;
    PWMB_SR1    = 0;
    PWMB_SR2    = 0;
    PWMB_ENO    = 0;
    PWMB_PS     = 0;
    PWMB_IER    = 0;
    PWMB_ISR_En = 0;

    PWMB_PSCR = 0;
    PWMB_DTR    = 0;    // 无死区
    PWMB_ARR    = 230; // 总周期 2000us

    // 通道2 → P5.4
    PWMB_CCR2   = 115;         // 延时1000us → 宽度1000us
    PWMB_CCMR2  = (7<<4) + 8;   // PWM模式2 + CCR预装载
    PWMB_CCER1 |= 0x50;         // 开启比较输出,高电平有效
    PWMB_PS    |= (1<<2);       // 路由到 P5.4
    PWMB_ENO   |= 0x04;         // IO使能 P5.4
    PWMB_BKR    = 0x80;         // 主输出使能
    PWMB_CR1   |= 0x08;         // 单脉冲模式


    PWMB_CCMR3   = 0x01;
    PWMB_CCER2  |= 0x01;
    PWMB_CCMR4   = 0x02;
    PWMB_CCER2  |= 0x30;
    PWMB_PS     |= 1;
    PWMB_ISR_En |= 0x08;
    PWMB_ISR_En |= 0x10;
    P3M0 &= ~0x08; P3M1 &= ~0x08;
    P33 = 1;

    PWMB_IER  = PWMB_ISR_En;
    PWMB_CR1 |= 0x01;
}

// 设置Timer2做波特率发生器
void SetTimer2Baudraye(u16 dat) // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
{
    AUXR &= ~(1<<4);    //Timer stop
    AUXR &= ~(1<<3);    //Timer2 set As Timer
    AUXR |=  (1<<2);    //Timer2 set as 1T mode
    TH2 = (u8)(dat >> 8);
    TL2 = (u8)dat;
    IE2  &= ~(1<<2);    //禁止中断
    AUXR |=  (1<<4);    //Timer run enable
}

// UART1初始化函数
void UART1_config(u32 brt, u8 timer, u8 io) // brt: 通信波特率,  timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,  =1: 切换到P3.6 P3.7,  =2: 切换到P1.6 P1.7.
{
    brt = 65536UL - (MAIN_Fosc / 4) / brt;
    if(timer == 2)  // 波特率使用定时器2
    {
        AUXR |= 0x01;       // S1 BRT Use Timer2;
        SetTimer2Baudraye((u16)brt);
    }

    else        // 波特率使用定时器1
    {
        TR1 = 0;
        AUXR &= ~0x01;      // S1 BRT Use Timer1;
        AUXR |=  (1<<6);    // Timer1 set as 1T mode
        TMOD &= ~(1<<6);    // Timer1 set As Timer
        TMOD &= ~0x30;      // Timer1_16bitAutoReload;
        TH1 = (u8)(brt >> 8);
        TL1 = (u8)brt;
        ET1 = 0;            // 禁止Timer1中断
        INT_CLKO &= ~0x02;  // Timer1不输出高速时钟
    //  INT_CLKO |=  0x02;  // Timer1输出高速时钟
        TR1  = 1;           // 运行Timer1
    }

         if(io == 1)    {S1_USE_P36P37();   P3n_standard(0xc0);}    // 切换到 P3.6 P3.7
    else if(io == 2)    {S1_USE_P16P17();   P1n_standard(0xc0);}    // 切换到 P1.6 P1.7
    else                {S1_USE_P30P31();   P3n_standard(0x03);}    // 切换到 P3.0 P3.1

    SCON = (SCON & 0x3f) | (1<<6);  // 8位数据, 1位起始位, 1位停止位, 无校验

    ES  = 1;    // 允许中断
    REN = 1;    // 允许接收
}

// 串口1查询发送一个字节函数
void UART1_TxByte(u8 dat)
{
    B_TX1_Busy = 1;     //标志发送忙
    SBUF = dat;     //发一个字节
    while(B_TX1_Busy);  //等待发送完成
}

// 串口1字符串打印函数
void PrintString1(u8 *puts)
{
    for (; *puts != 0;  puts++)     UART1_TxByte(*puts);
}


// 主函数
void main(void)
{
    P_SW2 |= 0x80;                          // SFR enable

    P5M0 |= 0x10; P5M1 &= ~0x10;            // P54推挽输出

    PWMB_config();
    UART1_config(115200UL, 1, 0);   // brt: 通信波特率,  timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,  =1: 切换到P3.6 P3.7,  =2: 切换到P1.6 P1.7.
    EA = 1;

    while (1)
    {
        if(B_Capture2)                      // 波形2捕捉完成
        {
            B_Capture2 = 0;
            ReturnValue();                  // 串口1返回周期和高电平时间
        }

        PWMB_CR1 |= 0x01;                   // 触发一次单脉冲输出
    }
}


// 中断服务函数
// 串口1中断函数
void UART1_ISR (void) interrupt UART1_VECTOR
{
    if(RI)
    {
        RI = 0;
    }

    if(TI)
    {
        TI = 0;
        B_TX1_Busy = 0;
    }
}

// PWMB中断处理程序. 读取捕获数据
void PWMB_ISR(void) interrupt PWMB_VECTOR
{
    u16 j;
    u8  sr1;
    sr1 = PWMB_SR1;                         // 为了快速, 中断标志用一个局部变量处理

    PWMB_SR1 = 0;                           // 清除中断标志
    PWMB_SR2 = 0;                           // 清除中断标志

    sr1 &= PWMB_ISR_En;                     // 每个通道可以单独允许中断处理

    if(sr1 & 0x08)                          // 通道3, CC3捕获上升沿中断, 一个周期结束, 新的周期开始
    {
        j = ccr3;                           // 上一个捕捉时刻
        ccr3 = PWMB_CCR3;                   // 读取当前捕捉时刻
        period2 = ccr3 - j;                 // 减去上一个捕捉时刻, 计算周期
        B_Capture2 = 1;                     // 标志波形2已捕捉完成
    }
    if(sr1 & 0x10)                          // 通道4, CC4捕获下降沿中断, 计算高电平时间
    {
        PulseHigh2 = PWMB_CCR4 - ccr3;      // 读取当前捕捉时刻, 计算高电平时间
    }
}现在这个程序
单独验证单脉冲 和 测频的时候都是ok的
但是一旦把这两个功能都放进PWMB里面 测频出问题了 并且脉冲频率也从170khz降到了167Khz 是不是不能放在一个PWM模块里啊


回复

使用道具 举报 送花

3

主题

1848

回帖

544

积分

等待验证会员

积分
544
发表于 2025-10-19 15:53:01 | 显示全部楼层
关于您提出的“PWMA B模块是否会资源互斥”的问题,以下是对该问题的详细分析与解答:

在使用STC8H系列单片机的PWMA(增强型脉宽调制)模块时,模块间的资源互斥问题是一个非常关键的配置考量点。所谓“资源互斥”,通常是指不同模块或通道之间是否共享某些硬件资源(如定时器、计数器、比较寄存器等),从而导致在同时使用时产生冲突或不可预知的行为。

一、PWMA模块的结构概述

STC8H系列单片机内置的PWMA模块为增强型PWM模块,支持多通道输出、频率与占空比独立调节、死区控制等功能。该模块通常由一个主定时器和多个独立通道组成,每个通道可以配置为独立的PWM输出。PWMA模块一般分为A、B、C等多个子模块(如PWMAB、PWMAC等),用于实现更灵活的PWM输出控制。

二、PWMAB模块与其他模块的资源使用情况

以PWMAB模块为例,其资源使用情况需参考数据手册中的“模块资源映射”部分。通常情况下:
定时器资源:多个PWMA子模块可能共享同一个主定时器作为计数源。例如,PWMAA、PWMAB、PWMAC可能共用PWMA的主定时器(如PWMxTimer)。这种情况下,这些模块的频率将被统一控制,无法各自独立设置频率,但占空比可独立配置。
通道资源:每个子模块通常包含多个通道(如4个通道),这些通道在内部使用独立的比较寄存器,因此在占空比设置上互不干扰。
中断资源:中断向量也可能存在共享情况,例如多个模块的中断可能共用一个中断入口,需通过软件判断中断源。

三、资源互斥的具体表现

若PWMAB模块与其他模块(如PWMAA)共享主定时器资源,则在配置时需注意以下几点:

1. 频率设置互斥:若多个模块共享同一主定时器,则它们的PWM频率必须一致,无法独立设置不同频率。
2. 占空比独立设置:每个通道的占空比由各自的比较寄存器控制,因此即使频率一致,占空比仍可独立调节。
3. 死区控制共享:若模块支持死区控制功能,死区时间可能为全局配置,影响所有使用该模块的通道。
4. 输出引脚冲突:在配置PWMAB模块的输出通道时,需注意引脚复用问题,避免与其他外设(如UART、SPI等)或其它PWM通道发生引脚冲突。

四、如何判断是否互斥

要准确判断PWMAB模块是否与其他模块存在资源互斥,建议参考以下方法:

1. 查阅数据手册:查看“增强型PWM模块”章节中关于模块资源分配的描述,确认PWMAB与其他模块是否共享主定时器、比较寄存器、中断源等。
2. 查看寄存器映射:通过查看PWM寄存器的地址分布,判断不同模块是否使用相同的寄存器地址空间。
3. 查阅官方应用笔记或示例代码:STC官方通常会提供相关配置示例,说明模块间的使用限制。

五、解决资源互斥的方法

若确实存在资源互斥问题,可通过以下方式规避或解决:
合理规划模块使用:避免在同一主定时器下配置多个需要不同频率的PWM模块。
使用不同PWM模块:如需不同频率输出,可选择使用不同主定时器驱动的PWM模块(如PWMA与PWMB)。
软件模拟PWM:对于非关键通道,可考虑使用定时器+GPIO翻转的方式实现软件PWM,避免资源冲突。
使用外置PWM芯片:在资源紧张时,可外挂PWM驱动芯片以扩展输出通道。

六、总结

综上所述,PWMAB模块是否与其他模块存在资源互斥,取决于其是否共享主定时器、中断源、比较寄存器等关键硬件资源。在实际使用中,应通过查阅技术手册和测试验证来确认模块间的兼容性。合理规划模块使用顺序和资源分配,是确保系统稳定运行的关键。

如需进一步分析具体配置代码或验证模块间的冲突情况,欢迎提供更详细的代码片段或配置参数,我将进一步协助您进行分析与优化。

如有技术手册或具体型号需求,建议提供完整型号(如STC8H8K64U)以便提供更精确的技术支持。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:225
  • 最近打卡:2025-11-01 08:22:10

792

主题

1万

回帖

2万

积分

管理员

积分
20133
发表于 2025-10-19 16:41:30 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 2025-10-19 17:20:04 | 显示全部楼层
神*** 发表于 2025-10-19 16:41
https://www.stcaimcu.com/data/download/Datasheet/STC8H.pdf

所以是要分成两个PWM来用么
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:216
  • 最近打卡:2025-10-31 11:24:48

83

主题

6818

回帖

1万

积分

超级版主

积分
14624
发表于 2025-10-19 17:46:49 | 显示全部楼层
可以,但是要注意公用一个计数器的问题。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:225
  • 最近打卡:2025-11-01 08:22:10

792

主题

1万

回帖

2万

积分

管理员

积分
20133
发表于 2025-10-19 18:43:40 | 显示全部楼层
截图202510191843093506.jpg


截图202510191843385587.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 2025-10-19 19:05:55 | 显示全部楼层
梁*** 发表于 2025-10-19 17:46
可以,但是要注意公用一个计数器的问题。

我现在这个程序这样能处理么
影响到我测频
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:544
  • 最近打卡:2025-10-31 09:14:02
已绑定手机

48

主题

2300

回帖

8120

积分

论坛元老

积分
8120
发表于 2025-10-20 09:04:30 | 显示全部楼层
这个帖子有介绍原因,并提供了相应的例子
截图202510201300049197.jpg

https://www.stcaimcu.com/forum.p ... id=20283&pid=187876

同组PWM捕获测量的周期值与PWM输出的周期相同,都是ARRH,ARRL。
由于同一组的PWM输出和捕获同步,如果PWM输出直接反馈接入到同组PWM捕获接口,
则每次捕获都刚好PWM溢出,计算出的周期值始终是0。
使能PWM输出时,如果使用同组PWM捕获外部输入信号有异常值,
是由于在发生捕获动作时将当前的计数值保存到PWMx_CCRn里面,但由于使能了PWM输出,
所以计数值到PWMx_ARR后就立即归零了
(正常是计数到FFFF再归零,开启输出后计数值到ARR值就立即归零)。

解决方法:1. 同一组PWM里面如果要输出和捕获同时进行,将ARR设置为FFFF。
2. 修改捕获计数方法:cnt = ((cnt1 - cnt2) % (PWMA_ARR + 1));
3. 捕获/输出分开两组PWM,例如:PWMA捕获PWMB输出
三种方法都可以解决以上问题。
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:34
  • 最近打卡:2025-10-30 10:47:29
已绑定手机

20

主题

67

回帖

209

积分

中级会员

积分
209
发表于 2025-10-20 12:01:33 | 显示全部楼层
乘风*** 发表于 2025-10-20 09:04
这个帖子有介绍原因,并提供了相应的例子
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost ...

好的我看一下
原来没有找到这个帖子
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-11-2 01:22 , Processed in 0.139797 second(s), 104 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表