一旦使用调用一个数的方式选择蜂鸣器的频率,蜂鸣器噼里啪啦地响,但直接赋值的话正常

问题如下:

#include 

sbit Buzzer=P2^5;

void Delay(unsigned int xms)
{
    unsigned char i,j;
    while(xms--)
    {
        i=2;
        j=239;
        do
        {
            while(--j);
        } while (--i);
    }
}

/**
   * @brief  定时器0初始化,1毫秒@12.000Mhz
   * @param  无
   * @retval 无
   */
void Timer0_Init()
{
    TMOD = TMOD & 0xF0; //低四位清零,高四位不变
    TMOD = TMOD | 0x01; //低四位赋值,高四位不变
    TL0 = 0x18; //设置定时初值
    TH0 = 0xFC; //设置定时初值
    TF0 = 0; //清除TF0溢出中断标志,加到65536后TF0会被置为1
    TR0 = 1; //允许定时器0计时
    ET0 = 1;
    EA  = 1;
    PT0 = 0;
}

//FrequencyTable 频率表
unsigned int FreqTable[]=
(     
     63461,63578,63688,63791,63889,63981,64069,64151,64229,64302,64371,64436,
     64498,64556,64611,64663,64712,64758,64802,64843,64882,64918,64953,64986,
     65017,65046,65073,65099,65124,65147,65168,65189,65208,65227,65244,65260
);

问题出在接下来的函数中

//频率选择
unsigned char FreqSelect;

void main()
{
    Timer0_Init();
    FreqSelect=1;
    while(1)
    {
        
    }
}

void Timer0_Routine() interrupt 1
{
    TL0 =FreqTable[FreqSelect]%256; //设置定时初值
    TH0 =FreqTable[FreqSelect]/256; //设置定时初值
    Buzzer=!Buzzer;
}

此处我通过从数组中调用定时器初值的方式来选择蜂鸣器的频率,但烧录到板子里后,蜂鸣器不正常响而是噼里啪啦地响。
或者直接赋值FreqSelect=63578;也是同样的效果


//FrequencyTable 频率表
unsigned int FreqTable[]=
(     
     63461,63578,63688,63791,63889,63981,64069,64151,64229,64302,64371,64436,
     64498,64556,64611,64663,64712,64758,64802,64843,64882,64918,64953,64986,
     65017,65046,65073,65099,65124,65147,65168,65189,65208,65227,65244,65260
);

//频率选择
unsigned char FreqSelect;

void main()
{
    Timer0_Init();
    FreqSelect=63578;
    while(1)
    {
        
    }
}

void Timer0_Routine() interrupt 1
{
    TL0 =FreqSelect%256; //设置定时初值
    TH0 FreqSelect/256; //设置定时初值
    Buzzer=!Buzzer;
}

若我直接给定时器赋初值,也赋上63578,如一下代码,蜂鸣器就能正常响

//FrequencyTable 频率表
unsigned int FreqTable[]=
(     
     63461,63578,63688,63791,63889,63981,64069,64151,64229,64302,64371,64436,
     64498,64556,64611,64663,64712,64758,64802,64843,64882,64918,64953,64986,
     65017,65046,65073,65099,65124,65147,65168,65189,65208,65227,65244,65260
);

//频率选择
unsigned char FreqSelect;

void main()
{
    Timer0_Init();
    FreqSelect=1;
    while(1)
    {
        
    }
}

void Timer0_Routine() interrupt 1
{
    TL0 =63578%256; //设置定时初值
    TH0 63578/256; //设置定时初值
    Buzzer=!Buzzer;
}

FreqSelect=63578;不行吧,FreqSelect是表的索引值,那个表可没那么长。而且FreqSelect只是个unsigned char。
另外试试FreqTable定义到code里,这个表默认是data类型,要占72个字节,有点大了。

中断函数里这么修改下,供参考:

void Timer0_Routine() interrupt 1
{
    Buzzer=!Buzzer;
    TR0 = 0;         //暂停定时器计时
    TL0 =FreqTable[FreqSelect]%256; //设置定时初值
    TH0 =FreqTable[FreqSelect]/256; //设置定时初值
    TR0 = 1;        //允许定时器0计时
}

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

找到原因了,一个很蠢的语法错误,我在定义数组时用了括号导致数组出错,应该把()改成{}。编译器没报错的原因,应该是把括号里的东西当成一个元素了,但是超出了unsigned int的范围,现象和把FreqSelect定义成unsigned char一样噼里啪啦(就是蜂鸣器很低频地发声),这种现象反映了数组越界 :)

unsigned int FreqTable[]=
(     //这里的括号改成花括号
     63461,63578,63688,63791,63889,63981,64069,64151,64229,64302,64371,64436,
     64498,64556,64611,64663,64712,64758,64802,64843,64882,64918,64953,64986,
     65017,65046,65073,65099,65124,65147,65168,65189,65208,65227,65244,65260
);