STC8H1K28 ADC采样查询 与 STC8H8K64 区别
本帖最后由 ldc521 于 2023-1-13 15:51 编辑问题如下:
1.用STC8H8K64U,通道8,P00口进行ADC采样,数据准确
2.用STC8H1K28, 同1的程序,通道8,P00口采样,数据只有1023,511,····等规律数字,而且不准,与外部电压不对应
程序如下:
/******************* IO配置函数 *******************/
void GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
//AD口设置为输入口
GPIO_InitStructure.Pin= GPIO_Pin_0; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_HighZ; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P0,&GPIO_InitStructure); //初始化
GPIO_InitStructure.Pin= GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //初始化
}
/******************* AD配置函数 *******************/
void ADC_config(void)
{
ADC_InitTypeDef ADC_InitStructure; //结构定义
ADC_InitStructure.ADC_SMPduty = 31; //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
ADC_InitStructure.ADC_CsSetup = 0; //ADC 通道选择时间控制 0(默认),1
ADC_InitStructure.ADC_CsHold = 1; //ADC 通道选择保持时间控制 0,1(默认),2,3
ADC_InitStructure.ADC_Speed = ADC_SPEED_2X1T; //设置 ADC 工作时钟频率 ADC_SPEED_2X1T~ADC_SPEED_2X16T
ADC_InitStructure.ADC_Power = ENABLE; //ADC功率允许/关闭 ENABLE,DISABLE
ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED; //ADC结果调整, ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
ADC_InitStructure.ADC_Priority = Priority_0; //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
ADC_InitStructure.ADC_Interrupt = DISABLE; //中断允许 ENABLE,DISABLE
ADC_Inilize(&ADC_InitStructure); //初始化
ADC_PowerControl(ENABLE); //单独的ADC电源操作函数, ENABLE或DISABLE
}
/***************串口初始化函数 *****************/
void UART_config(void)
{
COMx_InitDefine COMx_InitStructure; //结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2, 所以不用选择)
COMx_InitStructure.UART_BaudRate= 115200ul; //波特率, 110 ~ 115200
COMx_InitStructure.UART_RxEnable= ENABLE; //接收允许, ENABLE或DISABLE
COMx_InitStructure.UART_Interrupt = ENABLE; //中断允许, ENABLE或DISABLE
COMx_InitStructure.UART_Priority = Priority_0; //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
COMx_InitStructure.UART_P_SW = UART1_SW_P30_P31; //切换端口, UART2_SW_P10_P11,UART2_SW_P46_P47
UART_Configuration(UART1, &COMx_InitStructure); //初始化串口2 USART1,USART2,USART3,USART4
PrintString1("STC8 AD to UART2 Test Programme!\r\n"); //UART2发送一个字符串
}
/**********************************************/
void main(void)
{
u8 i = 8;
u16 j;
GPIO_config();
UART_config();
ADC_config();
EA = 1;
while (1)
{
//for(i=0; i<9; i++)
{
delay_ms(250);
//Get_ADCResult(i); //参数0~15,查询方式做一次ADC, 丢弃一次
j = Get_ADCResult(8); //参数0~15,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
TX1_write2buff('A');
TX1_write2buff('D');
TX1_write2buff(8+'0');
TX1_write2buff('=');
TX1_write2buff(j/1000 + '0');
TX1_write2buff(j%1000/100 + '0');
TX1_write2buff(j%100/10 + '0');
TX1_write2buff(j%10 + '0');
TX1_write2buff(' ');
TX1_write2buff(' ');
}
PrintString1("\r\n");
}
}
原理图如下:
硬件部分:
用示波器测量ADC_Vref脚基准电压与采样脚P00电压是否稳定,并提供MCU相关电路的原理图。
软件部分:
将 ADC_Speed 的参数 ADC_SPEED_2X1T 改成 ADC_SPEED_2X16T,增加ADC采样时间试试。 检查VCC、AVREF和ADC输入电压,是否正常。 梁工 发表于 2023-1-13 23:16
检查VCC、AVREF和ADC输入电压,是否正常。
VCC---3.3V正常
VREF---直连VCC---3.3V正常
ADC输入电压用直连可调电源输出正常,采样不对
ADC输入电压采用分压电阻方式,万用表测量电压正确,采样不对 乘风飞扬 发表于 2023-1-13 18:18
硬件部分:
用示波器测量ADC_Vref脚基准电压与采样脚P00电压是否稳定,并提供MCU相关电路的原理图。
软件部 ...
硬件方面,使用万用表测试基准电压与采样电压均准确
软件部分两款不同内存同型号的单片机,8K64就可以用 贴你完整的原理图的PDF, 软件将采样时间先设置到最长,用最新的STC-ISP软件, 看最新的数据手册
ldc521 发表于 2023-1-14 11:21
VCC---3.3V正常
VREF---直连VCC---3.3V正常
ADC输入电压用直连可调电源输出正常,采样不对
STC8H1K28 ADC与 STC8H8K64操作一模一样,没有区别,仅仅是ADC位数不同,前者是10位,后者是12位,如果你有计算,注意不要溢出。直接监测ADC值看看。 梁工 发表于 2023-1-14 13:31
STC8H1K28 ADC与 STC8H8K64操作一模一样,没有区别,仅仅是ADC位数不同,前者是10位,后者是12位,如果你 ...
我直接打印ADC的寄存器值,程序如下:
u16 Get_ADCResult(u8 channel) //channel = 0~15
{
u16 adc;
u8 i;
if(channel > ADC_CH15) return 4096; //错误,返回4096,调用的程序判断
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xf0) | ADC_START | channel;
NOP(10); //对ADC_CONTR操作后等待会儿再访问
for(i=0; i<250; i++) //超时
{
if(ADC_CONTR & ADC_FLAG)
{
ADC_CONTR &= ~ADC_FLAG;
if(ADCCFG &(1<<5)) //转换结果右对齐。
{
adc = ((u16)ADC_RES << 8) | ADC_RESL;
TX1_write2buff(ADC_RES);
TX1_write2buff(ADC_RESL);
}
else //转换结果左对齐。
{
#if ADC_RES_12BIT==1
adc = (u16)ADC_RES;
adc = (adc << 4) | ((ADC_RESL >> 4)&0x0f);
#else
adc = (u16)ADC_RES;
adc = (adc << 2) | ((ADC_RESL >> 6)&0x03);
#endif
}
return adc;
}
}
return 4096; //错误,返回4096,调用的程序判断
}
结果输出的数据如下:
1
3
7
F
1F
3F
7F
FF
1FF
3FF
可以随着电压的变化数据在变化,但是范围很小,到2V+就是3FF,到1.7V-就是000
但是同样的程序,同样的操作,放到8K64里,ADC采样的数据跟实际电压是同步的,而且通过公式可算 神农鼎 发表于 2023-1-14 11:54
贴你完整的原理图的PDF, 软件将采样时间先设置到最长,用最新的STC-ISP软件, 看最新的数据手册
现在已经把外围分压电路去掉了, 用可调电源直连MCU引脚