简介
最近用stm8s003k3开发项目,用到了ADC模块,记录一下笔记也分享一下心得
软件环境:STVD+COSMIC
硬件环境:STM8S003K3 TSSOP20封装
模块:ADC
1.ADC功能以及框图
由STM8S参考手册可以得到几个信息:
1、有ADC1和ADC2两个(实际上得看封装,我这款只有ADC1)
2、有多达16个输入通道(看封装,我这款只有2~6输入)
3、有好几个扩展功能
具体的功能如下所示
*由框图可以看出ADC1和ADC2差别还是有一点的,一些多引脚的芯片中ADC2的带模拟参考正负极,在模拟放大中,可通过减小参考电压来提供更大的分辨率。由于没有用到所以不考虑
*转换结束时可产生中断
*f MASTER 可以被分频2 到18
*ADC 输入电压范围:VSSA ≤ VIN ≤ VDDA
*可以选择ADC 专用外部中断(ADC_ETR)或者定时器触发信号(TRGO)来作为
外部触发信号
2.功能描述
2.1Enable/Disable ADC
2.2转换模式
ADC有五种转换模式:单次模式、连续模式、带缓存的连续模式、单词扫描模式、连续扫描模式,可以将以上模式分类便于理解
2.2.1ADC单通道:
A、要求:进行一次ADC转换,配置为单次模式使能,扫描模式关闭,这样ADC的这个通道转换一次后,就停止转换了。
B、要求:进行连续ADC转换,配置为连续模式使能,扫描模式关闭,这样ADC的这个通道转换一次后,接着进行下一次转换,不断连续。
2.2.2ADC多通道:
C、要求:进行一轮ADC转换:配置为单次模式使能,扫描模式使能,这样ADC的多个通道,按照配置的顺序依次转换一次后,就停止了。
D、要求:进行连续的ADC转换:配置为连续模式使能,扫描模式使能,这样ADC的多个通道,按照配置的顺序转换一次后,接着进行下一次转换,不断连续。
2.2.3结论:
扫描模式只在多通道的条件下有效,来使得各个通道按照配置循环依次转换,而单次模式无论在单通道还是多通道下只对这些或者这个通道进行一次转换
2.3对齐方式
通多ADC_CR2的ALIGN位控制对齐方式
2.4施密特触发器
施密特触发器是用于输入信号整形的,ADC应该不用施密特触发,才可以保持输入模拟信号的连续性 ,备注不用的ADC输入口如果禁止了施密特触发,比如UART的RX,在ADC初始化时禁止了施密特触发,该脚又复用为UART-RX,此时RX信号根本进不到UART接收模块中,将不能产生UART接收中断,后来当它打开施密特触发器后,URAT-RX接收也就正常了。
3.ADC初始化代码实现
static Adc_Config_t Adc_Config;
void Adc_Init(const Adc_Config_t * config)
{
memcpy(&Adc_Config, config, sizeof(Adc_Config));
/* 清空对齐标志位 */
ADC_CR2 &= (uint8_t)(~0x08);
/* ----------------------------------对齐方式 ----------------------------------*/
ADC_CR2 |= (uint8_t)Adc_Config.Align;
/* ---------------------------------转换方式 ----------------------------------*/
if (Adc_Config.Mode == 0x01)
{
/* 设置连续*/
ADC_CR1 |= 0x02;
}
else
{
/*设置单次转换模式 */
ADC_CR1 &= (uint8_t)(~0x02);
}
/* 清空ADC通道 */
ADC_CSR &= (uint8_t)(~ADC_CSR_CH);
/* 设置ADC的通道 */
ADC_CSR |= (uint8_t)(Adc_Config.Channel);
/* ------------------------------------ADC的分频------------------------------- */
/*清空寄存器 */
ADC_CR1 &= (uint8_t)(~0x70);
/*配置寄存器 */
ADC_CR1 |= (uint8_t)(Adc_Config.Prescaler);
/* ------------------------------------ADC的分触发方式------------------------------- */
/* 清空寄存器*/
ADC_CR2 &= (uint8_t)(~0x30);
/* 选择触发方式或关闭 */
ADC_CR2 |= (uint8_t)(Adc_Config.ExtTrig);
/* ----------------------------------配置要关闭的施密特触发器--------------------------------- */
ADC_TDRL |= (uint8_t)((uint8_t)0x01 << (uint8_t)Adc_Config.SchmittTrigg);
/* 使能ADC */
ADC_CR1 |= 0x01;
/* 使能ADC中断 */
ADC_CSR |= 0x20;
/* 开始转换,第二次开启哦 */
ADC_CR1 |= ((uint8_t)0x01)
}
然后在.h中定义我们要的枚举和结构体
typedef enum
{
ADC_ALIGN_LEFT = (uint8_t)0x00,
ADC_ALIGN_RIGHT = (uint8_t)0x08
} Adc_AlignType_t;
typedef enum
{
ADCDRV_CHANNEL2 = 0x02,
ADCDRV_CHANNEL3 = 0x03,
ADCDRV_CHANNEL4 = 0x04,
ADCDRV_CHANNEL5 = 0x05,
ADCDRV_CHANNEL6 = 0x06
} Adc_Channel_t;
typedef enum
{
ADC_EXTTRIG_TIM = (uint8_t)0x40,
ADC_EXTTRIG_GPIO = (uint8_t)0x50,
ADC_EXTTRIG_DISABLE = (uint8_t)0x00
} Adc_ExtTrig_TypeDef;
typedef enum
{
ADC_SCHMITTTRIG_CHANNEL2 = 0x02,
ADC_SCHMITTTRIG_CHANNEL3 = 0x03,
ADC_SCHMITTTRIG_CHANNEL4 = 0x04,
ADC_SCHMITTTRIG_CHANNEL5 = 0x05,
ADC_SCHMITTTRIG_CHANNEL6 = 0x06
} Adc_SchmittTrigg_TypeDef;
typedef enum
{
ADC_CONVERSIONMODE_SINGLE = (uint8_t)0x00,
ADC_CONVERSIONMODE_CONTINUOUS = (uint8_t)0x01
} Adc_ConversionMode_t;
typedef enum
{
ADC_PRESSEL_FCPU_D2 = (uint8_t)0x00,
ADC_PRESSEL_FCPU_D3 = (uint8_t)0x10,
ADC_PRESSEL_FCPU_D4 = (uint8_t)0x20,
ADC_PRESSEL_FCPU_D6 = (uint8_t)0x30,
ADC_PRESSEL_FCPU_D8 = (uint8_t)0x40,
ADC_PRESSEL_FCPU_D10 = (uint8_t)0x50,
ADC_PRESSEL_FCPU_D12 = (uint8_t)0x60,
ADC_PRESSEL_FCPU_D18 = (uint8_t)0x70
} Adc_PrescalerType_t;
typedef struct
{
Adc_ConversionMode_t Mode;
Adc_Channel_t Channel;
Adc_PrescalerType_t Prescaler;
Adc_AlignType_t Align;
Adc_ExtTrig_TypeDef ExtTrig;
Adc_SchmittTrigg_TypeDef SchmittTrigg;
} Adc_Config_t;
然后我们定义一个配置好参数的结构体,将这个结构体的首地址传进初始化函数就可以啦
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』