📄 hal_adc.c
字号:
/*
* --------------"拉普兰德K60底层库"-----------------
*
* 测试硬件平台:LPLD_K60 Card
* 版权所有:北京拉普兰德电子技术有限公司
* 网络销售:http://laplenden.taobao.com
* 公司门户:http://www.lpld.cn
*
* 文件名: HAL_ADC.c
* 用途: ADC底层模块相关函数
* 最后修改日期: 20120323
*
* 开发者使用协议:
* 本代码面向所有使用者开放源代码,开发者可以随意修改源代码。但本段及以上注释应
* 予以保留,不得更改或删除原版权所有者姓名。二次开发者可以加注二次版权所有者,
* 但应在遵守此协议的基础上,开放源代码、不得出售代码本身。
*/
#include "common.h"
#include "HAL_ADC.h"
//全局变量定义
tADC_Config Adc0_Config; // ADC0 寄存器结构体
tADC_Config Adc1_Config; // ADC0 寄存器结构体
//ADC映射地址数组
volatile ADC_MemMapPtr ADCx_Ptr[2] = {ADC0_BASE_PTR,
ADC1_BASE_PTR};
/*
* LPLD_ADC_Init
* ADC模块通用初始化函数--用于非中断模式、单次转换、软件触发
*
* 参数:
* adcx--ADC模块号
* |__ADC0 -ADC0模块
* |__ADC1 -ADC1模块
* mode--AD转换精度
* |__MODE_8 --单端8位,差分9位
* |__MODE_12 --单端12位,差分13位
* |__MODE_10 --单端10位,差分11位
* |__MODE_16 --单端16位,差分16位
* diff--单端输入或差分输入
* |__CONV_SING --单端
* |__CONV_DIFF --差分
*
* 输出:
* 0--配置错误
* 1--配置成功
*/
uint8 LPLD_ADC_Init(ADCx adcx, uint8 mode, uint8 diff)
{
tADC_ConfigPtr ADC_CfgPtr;
if(adcx == ADC0)
{
SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK); // 开启ADC0时钟
ADC_CfgPtr = &Adc0_Config;
}
else if(adcx == ADC1)
{
SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK); // 开启ADC1时钟
ADC_CfgPtr = &Adc1_Config;
}
else
{
return 0;
}
// 初始化ADC
// 首先进行32次的硬件平均校准
ADC_CfgPtr->CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_8) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_16)
| ADC_CFG1_ADICLK(ADICLK_BUS_2);
ADC_CfgPtr->CONFIG2 = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ;
ADC_CfgPtr->COMPARE1 = 0x1234u ;
ADC_CfgPtr->COMPARE2 = 0x5678u ;
ADC_CfgPtr->STATUS2 = ADTRG_SW | ACFE_DISABLED | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT);
ADC_CfgPtr->STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_32);
ADC_CfgPtr->PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64);
ADC_CfgPtr->STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31);
ADC_CfgPtr->STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31);
ADC_Config_Alt(ADCx_Ptr[adcx], ADC_CfgPtr); // 配置 ADC寄存器
ADC_Cal(ADCx_Ptr[adcx]); // 进行校准
// 重新为正常使用进行配置,4次硬件平均
// ADC输入时钟源为 BusClk/2
// ADC输入时钟分频为 1
// 长采样时间设置
ADC_CfgPtr->CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_1) | ADLSMP_LONG
| ADC_CFG1_ADICLK(ADICLK_BUS);
// 选择转换精度
switch(mode)
{
case MODE_8:
ADC_CfgPtr->CONFIG1 |= ADC_CFG1_MODE(MODE_8);
break;
case MODE_12:
ADC_CfgPtr->CONFIG1 |= ADC_CFG1_MODE(MODE_12);
break;
case MODE_10:
ADC_CfgPtr->CONFIG1 |= ADC_CFG1_MODE(MODE_10);
break;
case MODE_16:
ADC_CfgPtr->CONFIG1 |= ADC_CFG1_MODE(MODE_16);
break;
default:
return 0;
}
// 选择ADxxa为输入通道
// 异步时钟输出使能
// 高速转换
// 长采样时间时钟周期选择 额外20个时钟周期,共24个ADCK周期
// 总采样周期见K60技术文档 page:840
ADC_CfgPtr->CONFIG2 = MUXSEL_ADCA | ADACKEN_ENABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ;
ADC_CfgPtr->COMPARE1 = 0x1234u ;
ADC_CfgPtr->COMPARE2 = 0x5678u ;
ADC_CfgPtr->STATUS2 = ADTRG_SW | ACFE_DISABLED | ACFGT_GREATER | ACREN_DISABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT);
ADC_CfgPtr->STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_4);
ADC_CfgPtr->PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64);
//选择单端或差分模式
if(diff == CONV_SING)
{
ADC_CfgPtr->STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31);
}
else if(diff == CONV_DIFF)
{
ADC_CfgPtr->STATUS1A = AIEN_OFF | DIFF_DIFFERENTIAL | ADC_SC1_ADCH(31);
}
else
{
return 0;
}
ADC_Config_Alt(ADCx_Ptr[adcx], ADC_CfgPtr); // 配置ADC0
return 1;
}
/*
* LPLD_ADC_SE_Get
* 取得ADC模块单端输入转换值--软件触发
*
* 参数:
* adcx--ADC模块号
* |__ADC0 -ADC0模块
* |__ADC1 -ADC0模块
* channel--ADC通道号,不同的通道号对应不同的引脚,注意有些通道并非都有ADC0或ADC1
* |__0 --ADC0:PGA0_DP; ADC1:PGA1_DP
* |__1 --ADC0:PGA2_DP; ADC1:PGA3_DP
* |__2 --ADC0:PGA0_DP; ADC1:PGA1_DP
* |__3 --ADC0:ADC0_DP3; ADC1:PGA0_DP
* |__4 --ADC0:NC; ADC1:PTE0
* |__5 --ADC0:NC; ADC1:PTE1
* |__6 --ADC0:NC; ADC1:PTE2
* |__7 --ADC0:NC; ADC1:PTE3
* |__8 --ADC0:PTB0; ADC1:PTB0
* |__9 --ADC0:PTB1; ADC1:PTB1
* |__10 --ADC0:PTA7; ADC1:PTB4
* |__11 --ADC0:PTA8; ADC1:PTB5
* |__12 --ADC0:PTB2; ADC1:PTB6
* |__13 --ADC0:PTB3; ADC1:PTB7
* |__14 --ADC0:PTC0; ADC1:PTB10
* |__15 --ADC0:PTC1; ADC1:PTB11
* |__16 --ADC0:ADC0_SE16;ADC1:ADC1_SE16
* |__17 --ADC0:PTE24; ADC1:PTA17
* |__18 --ADC0:PTE25; ADC1:VREF Output
* |__19 --ADC0:PGA0_DM; ADC1:PGA1_DM
* |__20 --ADC0:PGA2_DM; ADC1:PGA3_DM
* |__23 --ADC0:DAC0_OUT;ADC1:DAC1_OUT
* |__26 --ADC0:Temperature Sensor; ADC1:Temperature Sensor
* |__27 --ADC0:Bandgap; ADC1:Bandgap
* |__29 --ADC0:VREFH; ADC1:VREFH
* |__30 --ADC0:VREFL; ADC1:VREFL
*
* 输出:
* 0--配置错误,或电压值为0
* 其他--AD通道转换值,右对齐
*/
uint16 LPLD_ADC_SE_Get(ADCx adcx, uint8 channel)
{
ADC_MemMapPtr adcptr = ADCx_Ptr[adcx];
if(channel>30)
return 0;
//不同的通道对应不同的引脚,因此需要判断并配置
if(adcx == ADC0)
{
switch(channel)
{
case 0: //ADC0_DP0 -- PGA0_DP
case 1: //ADC0_DP1 -- PGA2_DP
case 2: //PGA0_DP
case 3: //ADC0_DP3 -- PGA1_DP
break;
case 8: //ADC0_SE8 -- PTB0
case 9: //ADC0_SE9 -- PTB1
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORT_PCR_REG(PORTB_BASE_PTR, channel-8) = PORT_PCR_MUX(0);
break;
case 10: //ADC0_SE10 -- PTA7
case 11: //ADC0_SE11 -- PTA8
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;
PORT_PCR_REG(PORTA_BASE_PTR, channel-3) = PORT_PCR_MUX(0);
break;
case 12: //ADC0_SE12 -- PTB2
case 13: //ADC0_SE13 -- PTB3
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORT_PCR_REG(PORTB_BASE_PTR, channel-10) = PORT_PCR_MUX(0);
break;
case 14: //ADC0_SE14 -- PTC0
case 15: //ADC0_SE15 -- PTC1
SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;
PORT_PCR_REG(PORTC_BASE_PTR, channel-14) = PORT_PCR_MUX(0);
break;
case 16: //ADC0_SE16
break;
case 17: //ADC0_SE17 -- PTE24
case 18: //ADC0_SE17 -- PTE25
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
PORT_PCR_REG(PORTE_BASE_PTR, channel+7) = PORT_PCR_MUX(0);
break;
case 19: //ADC0_DM0 -- PGA0_DM
case 20: //ADC0_DM1 -- PGA2_DM
case 23: //ADC0_SE23 -- DAC0_OUT
case 26: //Temperature Sensor (S.E)
case 27: //Bandgap (S.E)
case 29: //VREFH (S.E)
case 30: //VREFL
break;
default:
return 0;
}
}
else if(adcx == ADC1)
{
switch(channel)
{
case 0: //ADC1_DP0 -- PGA1_DP
case 1: //ADC1_DP1 -- PGA3_DP
case 2: //PGA1_DP
case 3: //ADC1_DP3 -- PGA0_DP
break;
case 4: //ADC1_SE4a -- PTE0
case 5: //ADC1_SE5a -- PTE1
case 6: //ADC1_SE6a -- PTE2
case 7: //ADC1_SE7a -- PTE3
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
PORT_PCR_REG(PORTE_BASE_PTR, channel-4) = PORT_PCR_MUX(0);
break;
case 8: //ADC1_SE8 -- PTB0
case 9: //ADC1_SE9 -- PTB1
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORT_PCR_REG(PORTB_BASE_PTR, channel-8) = PORT_PCR_MUX(0);
break;
case 10: //ADC1_SE10 -- PTB4
case 11: //ADC1_SE11 -- PTB5
case 12: //ADC1_SE12 -- PTB6
case 13: //ADC1_SE13 -- PTB7
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORT_PCR_REG(PORTB_BASE_PTR, channel-6) = PORT_PCR_MUX(0);
break;
case 14: //ADC1_SE14 -- PTB10
case 15: //ADC1_SE15 -- PTB11
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
PORT_PCR_REG(PORTB_BASE_PTR, channel-4) = PORT_PCR_MUX(0);
break;
case 16: //ADC1_SE16
break;
case 17: //ADC1_SE17 -- PTA17
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;
PORT_PCR_REG(PORTA_BASE_PTR, channel) = PORT_PCR_MUX(0);
break;
case 18: //VREF Output
case 19: //ADC1_DM0 -- PGA1_DM
case 20: //ADC1_DM1 -- PGA3_DM
case 23: //DAC1_OUT
case 26: //Temperature Sensor (S.E)
case 27: //Bandgap (S.E)
case 29: //VREFH (S.E)
case 30: //VREFL
break;
default:
return 0;
}
}
else
{
return 0;
}
ADC_SC1_REG(adcptr,0) &= ~(ADC_SC1_ADCH_MASK);
ADC_SC1_REG(adcptr,0) |= ADC_SC1_ADCH(channel);
while((ADC_SC1_REG(adcptr,0)&ADC_SC1_COCO_MASK) == 0); //等待转换完成
return ADC_R_REG(adcptr, 0);
}
/*
* LPLD_ADC_SetHWTrg
* 设置ADC为硬件触发方式
*
* 参数:
* adcx--ADC模块号
* |__ADC0 -ADC0模块
* |__ADC1 -ADC0模块
*
* 输出:
* 无
*/
void LPLD_ADC_SetHWTrg(ADCx adcx)
{
ADC_MemMapPtr adcptr = ADCx_Ptr[adcx];
//选择ADC为硬件触发方式
ADC_SC2_REG(adcptr) |= ADC_SC2_ADTRG_MASK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -