本帖最后由 Ryanhsiung 于 2011-10-14 09:46 编辑
功能说明: 1、100ms 轮循 采集 片内温度、热敏电阻、可调电阻 3路AD
若去采集时没有转换完成,则跳出不采集。到下一个采集周期在采集,从而不必等待AD转换,以实现0耗时
2、每隔1S返回一次数据
程序说明:
1、本程序继承于我的 0耗时按键,先前按键程序保留着
2、AD采集结果没有进行过滤,结果使用8位整型保存
3、热敏电阻阻值与温度的关系是非线性的,我将10-40度近似看做线性,用公式来求温度
变换的公式我没有验证,若网友要引用请先验证后引用
关键代码如下:
int main (void)
{
User_SystemInit(); //初始化
while(1)
{
ClrWDT(); //喂狗
ADC_SerialOutMessage(); //输出AD信息,由systick驱动
}
}
系统滴答:
ivoid SysTick_Handler(void)
{
static uint8_t count = 0;
static uint8_t s_count = 0;
SysTic_ClearIF(); //向SYST_CSR.COUNTFLAG中写1 以清除标志
Button_Check(); //BUTTON检测
if( count++ >= 10 )
{
count = 0;
ADC_CollectTemp(); //AD检测
}
if(s_count++ >= 100 )
{
s_count = 0;
Flag_OneSecondForADC = 1 ; //用于驱动AD信息输出 }
}
下面是AD程序
#include "includes.h"
//特别说明 :本程序 底层是从lixiaoxu2meng那借鉴来的
static uint8_t ADC_CollectValue[ADC_CHANNEL_MAX_NUM]; //存放采集值
static ADC_Channel_Type ADC_Channel; //选择通道
/*************************************************************************************
** Function name: ADC_Configuration
** Descriptions: ADC配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ADC_Configuration(void)
{
// ADC_SINGLE_END AD为单端输入模式
// ADC_CONTINUOUS_OP 使用连续转换,若用单次采集则在采集完后必须重新打开采集 // ADC_SINGLE_OP 单一转换
// 821 GA7 GA1 AG0作为输入 模式输入通道使能 ,/以下函数会改变ADCHER.CHEN的值,所以后面ADCHER.CHEN都被注释掉了
// EXTERNAL_12MHZ ADC时钟为 外部12MHZ
// 11 AD时钟频率 = ADC时钟/(11+1) = 1MHZ
DrvADC_Open(ADC_SINGLE_END, ADC_CONTINUOUS_OP, 0x80|0x02|0x01, EXTERNAL_12MHZ, 11); //DrvADC_SetADCChannel(0x80|0x02|0x01,ADC_SINGLE_END);
ADC->ADCR.ADIE = 0; //关闭AD转换中断
ADC->ADCR.DMOF = 0; //转化结果无符号
//使能片内温度AD通道
SYS->TEMPCR = 0x01; //使能温度传感器
//ADC->ADCHER.CHEN |= 0x80; //模拟输入通道7使能 CHEN7 =1 ;
ADC->ADCHER.PRESEL = 0x02; //内部温度传感器
//使能热敏电阻AD通道
///ADC->ADCHER.CHEN |= 0x01; //模拟输入通道0使能 CHEN0 =1 ;
//使能可调电阻AD通道
///ADC->ADCHER.CHEN |= 0x01; //模拟输入通道1使能 CHEN1 =1 ;
DrvADC_StartConvert(); // 开启ADC转换 连续采集
}
/*************************************************************************************
** Function name: ADC_Variable_Init
** Descriptions: ADC变量初始化
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ADC_Variable_Init(void)
{
uint8_t i;
//暂无 若无变量初始化,该函数可省略
ADC_Channel = E_ADC_Channel_Chip_Temp;
for(i=0;i<ADC_CHANNEL_MAX_NUM;i++)
{
ADC_CollectValue[i] =0;
}
}
/*************************************************************************************
** Function name: ADC_Init
** Descriptions: ADC初始化
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ADC_Init(void)
{
ADC_Configuration();
ADC_Variable_Init();
printf("ADC 初始完成!!\n");
}
/*************************************************************************************
** Function name: ADC_CollectTemp
** Descriptions: 采集温度
** input parameters: none
** output parameters: none
** Returned value: none
** Remark; AD采样很快,但是我每隔100MS才取一次
*************************************************************************************/
void ADC_CollectTemp(void)
{ //若用单次采集则在采集完后必须重新打开采集
int32_t AD_Value; //用于存放AD值临时值
if(DrvADC_IsConversionDone()==TRUE); // 判断ADC是否转换结束
{ //不用等待,这里是0耗时的重点
switch(ADC_Channel)
{
case E_ADC_Channel_Chip_Temp: // 芯片温度
{
AD_Value = DrvADC_GetConversionData(7); // 取7通道,CHIP TEMP
AD_Value = AD_Value*3300/4095-730; // 还需经过校正,现是套用他人的校正因子
AD_Value = AD_Value/-2;
ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;
ADC_Channel = E_ADC_Channel_R_Temp; //选择一下个通道
}break;
case E_ADC_Channel_R_Temp: // 热敏电阻
{ //这个热敏电阻是非线性的,所以换算比较难做,最好用查表
//我这里将10 - 40度近似看作为线性,中间的温度偏差可以有好几度。
//由于这个热敏电阻无太大意义,故方程我没有验证,请广大网友不要随意应用,若要用请验证!
AD_Value = DrvADC_GetConversionData(0); // 取0通道,AD
AD_Value = ((((float)AD_Value)/4096)*-135)*((float)3300 /4095) + 85 ; // 还需经过校正
ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;
ADC_Channel = E_ADC_Channel_Resister; //选择一下个通道
}break;
case E_ADC_Channel_Resister: // 可调电阻
{
AD_Value = DrvADC_GetConversionData(1); // 取1通道,AD
AD_Value = AD_Value*3300/4095; // 还需经过校正
AD_Value = 100*((float)(3300 - AD_Value)/3300);
ADC_CollectValue[ADC_Channel] = (uint8_t)AD_Value;
ADC_Channel = E_ADC_Channel_Chip_Temp; //选择一下个通道
}break;
default:break;
}
}
}
/*************************************************************************************
** Function name: ADC_SerialOutMessage
** Descriptions: 通过时间事件驱动,每隔1S通过串口发送一次数据给上位机
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ADC_SerialOutMessage(void)
{
if(Flag_OneSecondForADC)
{
Flag_OneSecondForADC =0;
printf("芯片温度:%d C 热阻温度: %d C 电阻阻值: %d(0.1kΩ) \n",\
ADC_CollectValue[0],ADC_CollectValue[1],ADC_CollectValue[2]);
}
}
|