/********************************** (C) COPYRIGHT *******************************
* File Name : Main.c
* Author : WCH
* Version : V1.0
* Date : 2018/12/15
* Description : adc采样示例,包括温度检测、单通道检测、差分通道检测、TouchKey检测、中断方式采样。
*******************************************************************************/
#include "CH57x_common.h"
UINT16 abcBuff[40];
volatile UINT8 adclen;
void DebugInit(void)
{
GPIOA_SetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
}
int main()
{
UINT8 i;
signed short RoughCalib_Value=0; // ADC粗调偏差值
/* 配置串口调试 */
DebugInit();
PRINT( "Start @ChipID=%02X\n", R8_CHIP_ID );
/* 温度采样并输出, 包含数据粗校准 */
PRINT( "\n1.Temperature sampling...\n");
ADC_InterTSSampInit();
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到变量 RoughCalib_Value中,注意这个变量需要定义为有符号变量
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("\n");
/* 单通道采样:选择adc通道9做采样,对应 PA0引脚, 带数据校准功能 */
PRINT( "\n2.Single channel sampling...\n");
GPIOA_ModeCfg(GPIO_Pin_0, GPIO_ModeIN_Floating);
ADC_ExtSingleChSampInit( SampleFreq_3_2, ADC_PGA_0 );
/*
注意:数据校准包括 粗调和细调:
ADC_DataCalib_Rough() 是粗调函数,调用前需保证PA5引脚配置浮空输入模式,外部没有电压信号,在ADC初始化之后调用,一般调用一次,除非更改了ADC模式(增益改变)
ADC_DataCalib_Fine() 是细调函数,对于粗调过的数据进行拟合算法运算,得到更精确数据
*/
GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
PRINT("=%d \n", RoughCalib_Value);
ADC_ChannelCfg( 9 );
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
ADC_DataCalib_Fine( &abcBuff[i], ADC_PGA_0 );
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("\n");
/* 差分通道采样:选择adc通道0做采样,对应 PA4(AIN0)、PA12(AIN2) */
PRINT( "\n3.Diff channel sampling...\n");
GPIOA_ModeCfg(GPIO_Pin_4|GPIO_Pin_12, GPIO_ModeIN_Floating);
ADC_ExtDiffChSampInit( SampleFreq_3_2, ADC_PGA_0 );
ADC_ChannelCfg( 0 );
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("\n");
/* TouchKey采样:选择adc通道 2 做采样,对应 PA12 */
PRINT( "\n4.TouchKey sampling...\n");
GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_Floating);
TouchKey_ChSampInit();
ADC_ChannelCfg( 2 );
for(i=0; i<20; i++)
{
abcBuff[i] = TouchKey_ExcutSingleConver(0x20); // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("\n");
/* 单通道采样:中断方式,选择adc通道1做采样,对应 PA5引脚, 不带数据校准功能 */
PRINT( "\n5.Single channel sampling in interrupt mode...\n");
GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating);
ADC_ExtSingleChSampInit( SampleFreq_3_2, ADC_PGA_0 );
ADC_ChannelCfg( 1 );
NVIC_EnableIRQ(ADC_IRQn);
adclen = 0;
ADC_StartUp();
while(adclen < 20);
NVIC_DisableIRQ(ADC_IRQn);
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("\n");
while(1);
}
void ADC_IRQHandler(void) //adc中断服务程序
{
if(ADC_GetITStatus())
{
abcBuff[adclen] = ADC_ReadConverValue();
ADC_StartUp(); // 作用清除中断标志并开启新一轮采样
adclen ++;
}
}
这段代码是一个基于CH57x微控制器的ADC采样示例,包括温度检测、单通道检测、差分通道检测、TouchKey检测和中断方式采样。以下是逐行注释:
```c
#include "CH57x_common.h" // 引入CH57x通用头文件
UINT16 abcBuff[40]; // 定义一个数组用于存储ADC采样结果
volatile UINT8 adclen; // 定义一个变量用于记录ADC采样次数
void DebugInit(void)
{
GPIOA_SetBits(GPIO_Pin_9); // 设置GPIOA的第9位为高电平
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); // 配置GPIOA的第8位为上拉输入模式
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // 配置GPIOA的第9位为推挽输出模式,电流为5mA
UART1_DefInit(); // 初始化UART1
}
int main()
{
UINT8 i;
signed short RoughCalib_Value=0; // ADC粗调偏差值
/* 配置串口调试 */
DebugInit();
PRINT( "Start @ChipID=%02X
", R8_CHIP_ID );
/* 温度采样并输出, 包含数据粗校准 */
PRINT( "
1.Temperature sampling...
");
ADC_InterTSSampInit(); // 初始化内部温度传感器采样
RoughCalib_Value = ADC_DataCalib_Rough(); // 计算ADC内部偏差,记录到变量 RoughCalib_Value中,注意这个变量需要定义为有符号变量
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("
");
/* 单通道采样:选择adc通道9做采样,对应 PA0引脚, 带数据校准功能 */
PRINT( "
2.Single channel sampling...
");
GPIOA_ModeCfg(GPIO_Pin_0, GPIO_ModeIN_Floating); // 配置GPIOA的第0位为浮空输入模式
ADC_ExtSingleChSampInit( SampleFreq_3_2, ADC_PGA_0 ); // 初始化外部单通道采样,采样频率为3.2MHz,增益为1倍
/*
注意:数据校准包括 粗调和细调:
ADC_DataCalib_Rough() 是粗调函数,调用前需保证PA5引脚配置浮空输入模式,外部没有电压信号,在ADC初始化之后调用,一般调用一次,除非更改了ADC模式(增益改变)
ADC_DataCalib_Fine() 是细调函数,对于粗调过的数据进行拟合算法运算,得到更精确数据
*/
GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating); // 配置GPIOA的第5位为浮空输入模式
RoughCalib_Value = ADC_DataCalib_Rough(); // 计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
PRINT("=%d
", RoughCalib_Value);
ADC_ChannelCfg( 9 ); // 配置ADC通道为9
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
ADC_DataCalib_Fine( &abcBuff[i], ADC_PGA_0 ); // 对采样结果进行细调校准
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("
");
/* 差分通道采样:选择adc通道0做采样,对应 PA4(AIN0)、PA12(AIN2) */
PRINT( "
3.Diff channel sampling...
");
GPIOA_ModeCfg(GPIO_Pin_4|GPIO_Pin_12, GPIO_ModeIN_Floating); // 配置GPIOA的第4位和第12位为浮空输入模式
ADC_ExtDiffChSampInit( SampleFreq_3_2, ADC_PGA_0 ); // 初始化外部差分通道采样,采样频率为3.2MHz,增益为1倍
ADC_ChannelCfg( 0 ); // 配置ADC通道为0
for(i=0; i<20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("
");
/* TouchKey采样:选择adc通道 2 做采样,对应 PA12 */
PRINT( "
4.TouchKey sampling...
");
GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_Floating); // 配置GPIOA的第12位为浮空输入模式
TouchKey_ChSampInit(); // 初始化触摸按键通道采样
ADC_ChannelCfg( 2 ); // 配置ADC通道为2
for(i=0; i<20; i++)
{
abcBuff[i] = TouchKey_ExcutSingleConver(0x20); // 连续采样20次
}
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("
");
/* 单通道采样:中断方式,选择adc通道1做采样,对应 PA5引脚, 不带数据校准功能 */
PRINT( "
5.Single channel sampling in interrupt mode...
");
GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating); // 配置GPIOA的第5位为浮空输入模式
ADC_ExtSingleChSampInit( SampleFreq_3_2, ADC_PGA_0 ); // 初始化外部单通道采样,采样频率为3.2MHz,增益为1倍
ADC_ChannelCfg( 1 ); // 配置ADC通道为1
NVIC_EnableIRQ(ADC_IRQn); // 使能ADC中断
adclen = 0; // 初始化adclen为0
ADC_StartUp(); // 启动ADC采样
while(adclen < 20); // 等待adclen达到20
NVIC_DisableIRQ(ADC_IRQn); // 禁用ADC中断
for(i=0; i<20; i++)
{
PRINT("%d ", abcBuff[i]);
}PRINT("
");
while(1); // 无限循环
}
void ADC_IRQHandler(void) //adc中断服务程序
{
if(ADC_GetITStatus()) // 如果ADC中断标志位被置位
{
abcBuff[adclen] = ADC_ReadConverValue(); // 读取ADC转换结果并存入abcBuff数组
ADC_StartUp(); // 清除中断标志并开启新一轮采样
adclen ++; // adclen自增1
}
}
```
|
感谢分享