[技术问答] ML51TC0AE,运行了一段自己编的ADC函数后,单片机好像降级.....

[复制链接]
943|5
手机看帖
扫描二维码
随时随地手机跟帖
onlycook|  楼主 | 2021-10-15 15:38 | 显示全部楼层 |阅读模式
本帖最后由 onlycook 于 2021-10-15 15:40 编辑

调试程序中对延时时间变长感到疑惑,遂寻找其问题原因所在,最后发现问题是在运行了一个自己编的ADC函数后出现的。我把该函数定义放在官方BSP文件中的ADC.C中,并在adc.h中也有声明。并非系统时钟变慢,我特意添加了一段函数测试异常过程中CLKO输出仍为24MHz。又特意编了个while(1)函数测试IO口输出方波频率,改变while(1)函数中内容,正常和异常时IO口输出频率之比不尽相同,有异常是IO口方波频率是正常时的5倍的,有比率是5.5倍的,正符合12T单片机和1T单片机(当然也不是所有指令都是1T)同频处理指令速度之比。请问这个是新唐ML51系列单片机的BUG吗?

使用特权

评论回复
onlycook|  楼主 | 2021-10-15 15:41 | 显示全部楼层
问题补充 :

延时函数跟STC单片机时用的差不多:

void delay_ms(unsigned int ms)

{

   unsigned int i;

         do{

              i = 24000000 / 13000;

                          while(--i)          //14T per loop

                                {

                                        ;

                                }

     }while(--ms);

}

正常时同STC一样延时时间很准,出现问题时该延时时间整整变为正常值的7倍。比较符合12T单片机和1T单片机的延时函数时间之比,刚好为整数的。新唐的ML51系列是新推出的单片机吧,感觉还是有些莫名其妙的问题,希望新唐赶紧解决。


使用特权

评论回复
onlycook|  楼主 | 2021-10-15 15:42 | 显示全部楼层
问题补充 :

引起问题的ADC函数如下:
float Get_ADCResult(unsigned char channel)                //channel = 0~7,VBG
{
  unsigned int ADC_Result;
        unsigned char ozc;
        u8 n;
        u16        adc_value_all = 0;
        float        adc_avg;

        ADC_Open(ADC_SINGLE,channel);

        for ( ozc=0; ozc<3; ozc++ )                //读取并丢弃前3次ADC结果,以获取准确值
        {
                clr_ADCCON0_ADCF;                   //清零ADC转换完成标志位
                set_ADCCON0_ADCS;                   //开始转换
                while(!(ADCCON0&SET_BIT7));           //等待转换结束
        }

        ADCRH = 0; ADCRL = 0;                      //调试用,验证是否真的进行了ADC转换
        clr_ADCCON0_ADCF;
        set_ADCCON0_ADCS;

        for(n=0;n<1;n++)                //对所测ADC通道电压进行10次采样,计算平均值
        {
                set_PCON_IDLE;                          //为提高ADC准确度,ADC时单片机进入IDLE待机状态
                while(!(ADCCON0&SET_BIT7));
                ADC_Result = (ADCRH<<4) + ADCRL;
                adc_value_all += ADC_Result;        //对进行AD转换,并对转换值进行累加
                ADC_Result = 0;
        }
        adc_avg = adc_value_all/1.0+0.0001; //加上0.0001是为了排除5171/10.0被计算成为517.0999的情况
        return        adc_avg;        
}


使用特权

评论回复
onlycook|  楼主 | 2021-10-15 15:45 | 显示全部楼层
问题补充 :

ML51_BSP_Keil_C51文件中的示例文件(StdDriver目录下的)ADC_Simple,将其代码改为如下,便可出现上述问题。

/*---------------------------------------------------------------------------------------------------------*/

/*                                                                                                         */

/* Copyright(c) 2019 Nuvoton Technology Corp. All rights reserved.                                         */

/*                                                                                                         */

/*---------------------------------------------------------------------------------------------------------*/


//***********************************************************************************************************

//  Website: http://www.nuvoton.com

//  E-Mail : MicroC-8bit@nuvoton.com

//***********************************************************************************************************


//***********************************************************************************************************

//  File Function: ML51 series ADC software trigger on shot demo code

//***********************************************************************************************************

#include "ML51.h"



#define en_MPW_CTR()  P56_PUSHPULL_MODE, SFRS = 0x00,        P5 |= SET_BIT6        //P56脚推挽输出高电平

#define dis_MPW_CTR() P56_PUSHPULL_MODE, SFRS = 0x00,        P5 &= CLR_BIT6        //P56脚推挽输出低电平



void ADC_ISR (void) interrupt 11

{

        ;

//   clr_ADCCON0_ADCF;                //clear ADC interrupt flag

}



void main ()

{

  unsigned int ADCRESULT;


          MFP_P16_UART0_TXD;                //设置P16为串口0输出

          P16_PUSHPULL_MODE;

    UART_Open(24000000,UART0_Timer3,115200);   // Open UART0 use timer1 as baudrate generate and baud rate = 115200

    ENABLE_UART0_PRINTF;


                ENABLE_ADC_INTERRUPT;

                ENABLE_GLOBAL_INTERRUPT;


                ADC_Open(ADC_SINGLE,1);                 //Enable ADC_CH4

    ADC_ConvertTime(3,7);


                clr_ADCCON0_ADCF;

    set_ADCCON0_ADCS;                       // Software trig adc start

    while((ADCCON0|CLR_BIT7)==CLR_BIT7);    // wait ADCF = 1;

    ADCRESULT = (ADCRH<<4)+ADCRL;

    printf("\n ADC result = 0x%X  ", ADCRESULT);

           Timer0_Delay(24000000,100,1000);


        while(1)

        {

                en_MPW_CTR();

                dis_MPW_CTR();

        }

               

}


,如果禁止ADC中断则不会出现上述问题。


使用特权

评论回复
内政奇才| | 2021-10-15 15:49 | 显示全部楼层
可能是SFRS  page切换的问题。主循环中刚刚切换到page1,立马被中断打断了,中断里切换到page0后没有恢复到page1,就导主循环后的执行的语句就不对了。所以在中断有对SFR操作的内容,都需要在中断里备份SFRS的状态才行。

使用特权

评论回复
skyred| | 2021-10-18 10:31 | 显示全部楼层
这个问题,有些好奇,
不过建议不要弄到bsp里,自己弄个c文件

使用特权

评论回复
您需要登录后才可以回帖 登录 | 注册

本版积分规则