调试程序中对延时时间变长感到疑惑,遂寻找其问题原因所在,最后发现问题是在运行了一个自己编的ADC函数后出现的。我把该函数定义放在官方BSP文件中的ADC.C中,并在adc.h中也有声明。并非系统时钟变慢,我特意添加了一段函数测试异常过程中CLKO输出仍为24MHz。又特意编了个while(1)函数测试IO口输出方波频率,改变while(1)函数中内容,正常和异常时IO口输出频率之比不尽相同,有异常是IO口方波频率是正常时的5倍的,有比率是5.5倍的,正符合12T单片机和1T单片机(当然也不是所有指令都是1T)同频处理指令速度之比。请问这个是新唐ML51系列单片机的BUG吗?
问题补充 : 2019/09/18 15:35
延时函数跟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系列是新推出的单片机吧,感觉还是有些莫名其妙的问题,希望新唐赶紧解决。
问题补充 : 2019/09/18 15:45
引起问题的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;
}
问题补充 : 2019/09/18 17:51
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中断则不会出现上述问题。 |