STC8H_ADC函数使用

这篇博客介绍了STC8H系列单片机中ADC(模拟数字转换器)的使用,包括5个通道的引脚配置、ADC控制寄存器、转换结果寄存器和时序控制。提供了ADC初始化和转换的函数实现,并展示了如何通过定时器进行ADC扫描及电压读取。代码示例涵盖了多个通道的ADC初始化和读取操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原理图部分

ADC使用了5个通道的引脚,分别为P1.1、P1.0、P3.6、P3.5、P3.4 。注意单片机要与测量物进行共地处理
在这里插入图片描述

ADC相关的寄存器

在这里插入图片描述

ADC控制寄存器(ADC_CONTR),PWM触发ADC控制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ADC转换结果寄存器(ADC_RES,ADC_RESL)

在这里插入图片描述

ADC时序控制寄存器

在这里插入图片描述

ADC速度计算公式

在这里插入图片描述

代码部分

封装好了各个通道的ADC的初始化和转换函数直接调用即可


#ifndef _ADC_H_
#define _ADC_H_

uint8  setbit = 0;
typedef enum
{
	ADC_P10 = 0,
	ADC_P11,
	ADC_P12, //仅做占位
	ADC_P13,
	ADC_P14,
	ADC_P15,
	ADC_P16,
	ADC_P17,

	ADC_P00,
	ADC_P01,
	ADC_P02,
	ADC_P03,
	ADC_P04,
	ADC_P05,
	ADC_P06,
	ADC_REF = 0x0f, //内部AD 1.19V

	ADC_P30,
	ADC_P31,
	ADC_P32,
	ADC_P33,
	ADC_P34,
	ADC_P35,
	ADC_P36,
	ADC_P37,

} ADC_Name;

//此枚举定义不允许用户修改
typedef enum
{
	ADC_SYSclk_DIV_2 = 0,
	ADC_SYSclk_DIV_4,
	ADC_SYSclk_DIV_6,
	ADC_SYSclk_DIV_8,
	ADC_SYSclk_DIV_10,
	ADC_SYSclk_DIV_12,
	ADC_SYSclk_DIV_14,
	ADC_SYSclk_DIV_16,
	ADC_SYSclk_DIV_18,
	ADC_SYSclk_DIV_20,
	ADC_SYSclk_DIV_22,
	ADC_SYSclk_DIV_24,
	ADC_SYSclk_DIV_26,
	ADC_SYSclk_DIV_28,
	ADC_SYSclk_DIV_30,
	ADC_SYSclk_DIV_32,
} ADC_CLK;


//此枚举定义不允许用户修改
typedef enum    // 枚举ADC通道
{

	ADC_12BIT = 0,    //12位分辨率
	ADC_11BIT,		//11位分辨率
	ADC_10BIT,		//10位分辨率
	ADC_9BIT,    	//9位分辨率
	ADC_8BIT,     	//8位分辨率

}ADC_bit;

//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC初始化
//  @param      adcn            选择ADC通道
//  @param      speed      		ADC时钟频率
//  @return     void
//  Sample usage:               adc_init(ADC_P10,ADC_SYSclk_DIV_2);//初始化P1.0为ADC功能,ADC时钟频率:SYSclk/2
//-------------------------------------------------------------------------------------------------------------------
void adc_init(ADC_Name adcn, ADC_CLK speed, ADC_bit _sbit)
{
	setbit = _sbit;
	ADC_CONTR |= 1 << 7;	//1 :打开 ADC 电源
	if (adcn > 15) 
	{
		adcn = adcn - 16;
		//IO口需要设置为高阻输入
		P3M0 &= ~(1 << (adcn & 0x07));
		P3M1 |= (1 << (adcn & 0x07));


	}
	else {
		if ((adcn >> 3) == 1) //P0.0
		{
			//IO口需要设置为高阻输入
			P0M0 &= ~(1 << (adcn & 0x07));
			P0M1 |= (1 << (adcn & 0x07));
		}
		else if ((adcn >> 3) == 0) //P1.0	
		{
			//IO口需要设置为高阻输入
			P1M0 &= ~(1 << (adcn & 0x07));
			P1M1 |= (1 << (adcn & 0x07));
		}
	}

	ADCCFG |= speed & 0x0F;	//ADC时钟频率SYSclk/2/speed&0x0F;

	ADCCFG |= 1 << 5;		//转换结果右对齐。 ADC_RES 保存结果的高 2 位, ADC_RESL 保存结果的低 8 位。

}



//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC转换一次
//  @param      adcn            选择ADC通道
//  @param      resolution      分辨率
//  @return     void
 //-------------------------------------------------------------------------------------------------------------------
uint16 adc_read(ADC_Name adcn)
{
	uint16 adc_value;
	if (adcn > 15)adcn = adcn - 8;

	ADC_CONTR &= (0xF0);	//清除ADC_CHS[3:0] : ADC 模拟通道选择位
	ADC_CONTR |= adcn;

	ADC_CONTR |= 0x40;  // 启动 AD 转换
	while (!(ADC_CONTR & 0x20));  // 查询 ADC 完成标志
	ADC_CONTR &= ~0x20;  // 清完成标志


	adc_value = ADC_RES;  //存储 ADC 的 10 位结果的高 2 位
	adc_value <<= 8;
	adc_value |= ADC_RESL;  //存储 ADC 的 10 位结果的低 8 位

	ADC_RES = 0;
	ADC_RESL = 0;

	adc_value >>= setbit;//取多少位


	return adc_value;
}

#endif

主函数部分

	//ADC初始化--------------
  adc_init(ADC_P11, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
  adc_init(ADC_P10, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
  adc_init(ADC_P36, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
  adc_init(ADC_P35, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
  adc_init(ADC_P34, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
	//ADC初始化--------------

定时器进行定时扫描打印出对应的电压

		printf_Valtage= MCU_Valtage_count * adc_read(ADC_P10);//连接到4号轴
//		printf("通道4电压 : %dmV\r\n", printf_Valtage);

		printf_Valtage= MCU_Valtage_count * adc_read(ADC_P11);//连接到1号轴
//		printf("通道1电压 : %dmV\r\n", printf_Valtage);		

		printf_Valtage= MCU_Valtage_count * adc_read(ADC_P34);//连接到5号轴
//		printf("通道5电压 : %dmV\r\n", printf_Valtage);

		printf_Valtage= MCU_Valtage_count * adc_read(ADC_P35);//连接到6号轴
//		printf("通道6电压 : %dmV\r\n", printf_Valtage);	

		printf_Valtage= MCU_Valtage_count * adc_read(ADC_P36);//连接到7号轴
//		printf("通道7电压 : %dmV\r\n", printf_Valtage);	

STC8H1K单片机(System Technology Corporation)是一款8位微控制器,其内置了ADC(Analog-to-Digital Converter,模拟到数字转换器)。使用ADC进行中断操作通常涉及到以下步骤: 1. **配置ADC模块**: - 首先,你需要初始化ADC,设置转换模式、通道选择、采样时间等。例如,你可以调用`ADC_Init()`函数配置ADC。 ```c void ADC_Init(void) { // 设置ADC寄存器和配置 ADC_InitStructure.ADC_Mode = ADC_Mode_ContinuousConv; ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单次转换或连续扫描 ADC_InitStructure.ADC_NbrOfChannel = 1; // 如果只有一个通道 ADC_Init(&ADC_InitStructure); } ``` 2. **启用中断**: - 打开ADC中断,在这里通常是当转换完成后触发中断。这通常通过设置中断使能标志并开启全局中断。 ```c void ADC_Enable_IT(ADC_TypeDef* ADCx, ADC_FLAG eADCFlag) { ADC_Cmd(ADCx, ENABLE); // 开启ADC模块 __enable_INT(); // 全局中断使能 if (eADCFlag == ADC_FLAG_ADRDY) { // 如果等待的是转换完成标志 ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE); // 启动EOC(End Of Conversion)中断 } } ``` 3. **中断服务函数**: - 编写一个中断服务函数(ISR),该函数会在ADC转换结束后被调用。在这个函数中,你可以读取ADC的结果。 ```c void EXTI0_IRQHandler(void) { static uint16_t adc_result; // 检查是否是ADC中断 if (__HAL_GET_IT_SOURCE(EXTI_LINE0) & IT_ADC) { ADC_ReadResult(&adc_result); // 从ADC获取结果 // 处理中断逻辑,如数据处理、存储或更新UI等 ADC_ClearITPendingBit(ADC, ADC_IT_EOC); // 清除中断标志 } } ``` 4. **清理中断**: - 在中断服务函数末尾,确保清除中断标志,以便下一次转换可以正常触发。 5. **中断后处理**: - 根据中断后的处理需求,可能需要执行其他任务,比如关闭中断、继续下一个转换等。 记得检查相关的头文件和库函数定义,因为这些可能会根据实际编译环境略有不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢谢~谢先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值