zhang32568 发表于 2026-5-11 19:56:04

STC32G12K128, PWM-DAC频率问题?时钟源如何设置

PWM作为载波输出音频信号。目前8位PWM。主频24M .载波频率40Khz.通过二阶阻容滤波效果不好。莎莎声明显。

将主频调高到25M9位PWM 。此时载波频率大概34K .偏低。但是听感明显比8位PWM好
现在想做10位PWM 。但是主频不能在高。PWM时钟源如何设置?

现在的想法是系统工作主频24M .经过2分频=12M 然后*8 =96M 作为PWM的高级时钟源。通过P34端口输出。这样可以输出11位PWM。载波频率大概在48K左右。

梁工 发表于 2026-5-11 22:11:33

下载下面帖子的例程包,解压缩,参考两个程序:
01B-HSPWMA-4对互补PWM输出P2口
02B-HSPWMB-4个单端PWM输出P2口

HSPWM的时钟是144MHz,40KHz的PWM频率,可以得到幅度为3600的PWM,音质会很好。

STC32G-高级PWM范例程序下载
https://www.stcaimcu.com/thread-1778-1-1.html
(出处: 国芯人工智能技术交流网站)

zhang32568 发表于 2026-5-12 15:30:14

梁工 发表于 2026-5-11 22:11
下载下面帖子的例程包,解压缩,参考两个程序:
01B-HSPWMA-4对互补PWM输出P2口
02B-HSPWMB-4个单端PWM输出 ...

谢谢梁工:已经设置成功。还有一个问题想请教一下。我测试通过CAN发送8点正弦波。非常稳定正常。但是传输实际音频的时候失真很严重,我的音频采集是通过DMA 。转换两次。然后经过A_LOW编码发送。语音采样率8K,每32毫秒采集256字节。通过编码输出128字节。(标准帧32帧)采集和解码都是双缓冲。采集A 发送B 。采集满256字节发送标志==1.在主循环发送32帧。(实际测试接收时间不丢包需要12.5毫秒)。DMA在定时器中断125us触发一次。困惑很久没找到原因。现在真实音频是信号源产生1K正弦波。收到失真抖动。unsigned char ALAW_Encode(int pcm)
{
    unsigned char sign, comp, seg;
    unsigned int temp;

    if (pcm >= 0)
    {
      sign = 0;
      temp = pcm;
    }
    else
    {
      sign = 0x80;
      temp = -pcm;
    }

    if (temp > 32635) temp = 32635;
    temp += 33;

    if (temp >= 16384)      seg = 7;
    else if (temp >= 8192)seg = 6;
    else if (temp >= 4096)seg = 5;
    else if (temp >= 2048)seg = 4;
    else if (temp >= 1024)seg = 3;
    else if (temp >= 512)   seg = 2;
    else if (temp >= 256)   seg = 1;
    else                  seg = 0;

    comp = (seg << 4) | ((temp >> (seg + 3)) & 0x0F);
    comp ^= 0x55;
    return sign | comp;
}

// A-LAW解码实现
int ALAW_Decode(unsigned char alaw)
{
    unsigned char sign, seg;
    unsigned int temp;

    alaw ^= 0x55;
    sign = alaw & 0x80;
    alaw &= 0x7F;

    seg = (alaw >> 4) & 0x07;
    temp = (0x80 | (alaw & 0x0F)) << (seg + 3);
    temp -= 33;

    if (seg != 0)
      temp += 4 << seg;

    if (sign) return -(int)temp;
    else return (int)temp;
}

// A-LAW块编码:256个PCM样本→256字节A-LAW数据
void alaw_encode_block(int *in, unsigned char *out, unsigned int n)
{
    unsigned int i;
    int sample16;
    for (i = 0; i < n; i++)
    {
      // 原PCM是12bit(-2048~2047),扩展到16bit适配A-LAW
      sample16 = in<< 4;
      out = ALAW_Encode(sample16);
    }
}

// A-LAW块解码:256字节A-LAW→256个PCM样本
void alaw_decode_block(unsigned char *in, int *out, unsigned int n)
{
    unsigned int i;
    int pcm16;
    for (i = 0; i < n; i++)
    {
      pcm16 = ALAW_Decode(in);
      // 还原为12bit PCM
      out = pcm16 >> 2;
    }
}

void prepare_pwm_buf(int *pcm, unsigned int *pwm, unsigned int n)
{
    unsigned int i;
    long val;
//    unsigned long temp;
   
    for (i = 0; i < n; i++)
    {
      val = (long)pcm + 2048;
      if (val < 10)val = 10;
      if (val > 4085) val = 4085;
//       temp = (unsigned long)(val - 10) * 255;
//      pwm = (unsigned char)(temp / (4085 - 10));
                        pwm = (val - 10) * 511 / 4075;
    }
}
void Timer0_ISR(void) interrupt 1
{
    // 输出当前采样点的PWM占空比
    PWM_SetDuty(rx_pwm);

    // 播放指针+1
    play_pos++;

    // 播放完一帧256点,回到0重新开始
    if(play_pos >= PCM_SAMPLE_NUM)
    {
      play_pos=0;
      silence_cnt++;// 静音计数+1

      // 连续多帧没收到新数据 → 填充静音,防止噪音
      if(silence_cnt>3)
      {
            fill_silence(rx_pwm, PCM_SAMPLE_NUM);
            silence_cnt=0;
      }
    }
}不知道哪里的问题?

梁工 发表于 2026-5-12 16:20:13

zhang32568 发表于 2026-5-12 15:30
谢谢梁工:已经设置成功。还有一个问题想请教一下。我测试通过CAN发送8点正弦波。非常稳定正常。但是传输 ...

还没空详细看代码。
“语音采样率8K,每32毫秒采集256字节。通过编码输出128字节。”这个是错误的,应该是“语音采样率8K,每32毫秒采集256点512字节,通过A-LAW编码输出256点256字节数据。”

zhang32568 发表于 2026-5-12 18:03:23

梁工 发表于 2026-5-12 16:20
还没空详细看代码。
“语音采样率8K,每32毫秒采集256字节。通过编码输出128字节。”这个是错误的,应 ...

啊 。256点。每个点12位需要两个字节512字节。我前面说错了。压缩后256字节。发送32帧。每帧8字节。32*8 = 256 没有错

梁工 发表于 2026-5-12 18:19:13

zhang32568 发表于 2026-5-12 18:03
啊 。256点。每个点12位需要两个字节512字节。我前面说错了。压缩后256字节。发送32帧。每帧8字节。32* ...

A-LAW是一种折叠码,要处理正确哦,8K采样声音也很好的。
页: [1]
查看完整版本: STC32G12K128, PWM-DAC频率问题?时钟源如何设置