欢迎光临~啄木鸟电子科技

软件设计

ADC 模拟信号 采集 转 数字信号

/*******************************************************************************/ 
// 功能:模拟信号 转 数字信号 (电压采集) 

/*******************************************************************************/ 
// 头文件 宏定义
#include <iostm8s003f3.h>
#include"stdio.h"

/*******************************************************************************/ 
//常用数据类型定义
#define u8  uint8_t
#define u16 uint16_t
#define u32 uint32_t
typedef unsigned char    uint8_t;
typedef unsigned int     uint16_t;
typedef unsigned long    uint32_t;

/*******************************************************************************/ 
//端口/引脚定义区域
// HC595 各 移位数据 输出并口控制 RCK
#define     RCLK_1     	PC_ODR_ODR6 = 1 
#define     RCLK_0   	PC_ODR_ODR6 = 0 

// HC595 时钟端口 控制 SCK 
#define     CLK_1     	PC_ODR_ODR7 = 1   
#define     CLK_0   	PC_ODR_ODR7 = 0 

// HC595 数据端口 控制 SER
#define     DAT_1     	PD_ODR_ODR2 = 1 
#define     DAT_0   	PD_ODR_ODR2 = 0 

/*******************************************************************************/ 
//用户自定义数据区域
static u16   AD_Vtemp[10] = {0};    // 装载 10次 ADC 采样数据
static u16   AD_val = 0;            // ADC 单次 采样数据
static u16   GET_voltage = 0;       // 获取到的 电压
const  u16   SET_V = 1500;          // 使用 const常量 定义电压 阈值

const  u16   V_ref = 5210;          // 使用 const常量 定义 当前电压参考值
const  u16   Low_V = 1000;          // 使用 const常量 定义 低电压 阈值
const  u16   Heigh_V = 4000;        // 使用 const常量 定义 高电压 阈值

/*******************************************************************************/ 
//用户自定义数据区域
//数码管 0 ~ F 的代码数组
unsigned char const Data[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e}; // 值( 7位 段码 共阳 );  
unsigned char const Wu[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};   // 位( 要不断的扫描);  

u8  number[8], SMGtimes, SMGBit;
u16 ms_count;
u8 time_n  = 0;

/*******************************************************************************/ 
//函数声明区域
void delay(u16 Count);          	//延时函数
void delay18B20(u16 Count);     	//DS18B20延时函数   

void ADC_init(void);
void ADC_GET(void);
void AVG_AD_Vtemp(void);

void HC595_WriteData(u8 data , u8 wu);


/*******************************************************************************
**函数名称:void HC595_WriteData(u8 data , u8 wu)
**功能描述:数码管显示
**入口参数:data->要显示的数据 , wu->设置要第几位数码管显示 
**输出:无
*******************************************************************************/
void HC595_WriteData(u8 data , u8 wu)
{
  	u8 i;
  	u16 tempdata;
  
  	tempdata = (u16)(wu);    	// 先把8位码放入16位里
  	tempdata <<= 8;          	// 把8位位码移到高8位先发送
  	tempdata |= data;       	// 再把段码8位放在低8位发送
  
  	RCLK_0;   					// 先把输出存储锁存时钟线拉低
  	for(i = 0 ; i < 16 ; i++)
  	{
    	CLK_0;  				// 数据输入时钟线拉低
    	if(tempdata & 0x8000)  	// 判断数据,把数据架在输出数据位上
    	{
      		DAT_1;
    	}
    	else
    	{
       		DAT_0;
    	}
     	CLK_1;       			// 把时钟线拉高,把移位数据输入并移位
    	tempdata <<= 1;   		// 把新数据架在输出数据线上
  	}
  	CLK_0;
  
  	RCLK_1;         			// 把输出存储锁存时钟线拉高,把595的移位数据输出到并口  
}

/*******************************************************************************
**函数名称:Init_NumericDisplay()
**功能描述:初始化位码控制芯片和段码控制芯片74HC164D的时钟和数据 相应的IO控制参数初始化
**入口参数:无
**输出:无
*******************************************************************************/
void Init_NumericDisplay()
{
  //2片 HC595 芯片  引脚初始化
  PC_DDR_DDR6 = 1;  // 输出方向
  PC_CR1_C16  = 1;  // 推挽输出
  PC_CR2_C26  = 1;  // 高速10MHZ  
  
  //2片 HC595 芯片  引脚初始化
  PC_DDR_DDR7 = 1;  // 输出方向
  PC_CR1_C17  = 1;  // 推挽输出
  PC_CR2_C27  = 1;  // 高速10MHZ  
  
  //HC595 芯片      引脚初始化
  PD_DDR_DDR2 = 1;  // 输出方向
  PD_CR1_C12  = 1;  // 推挽输出
  PD_CR2_C22  = 1;  // 高速10MHZ  
}

/**********************************************************************
* 函数: Init_CLK(void)
* 功能: 时钟设置;配置成 16MHz; 
* 输入: 无;
* 输出: 无;
***********************************************************************/
void Init_CLK(void)
{
	CLK_CKDIVR = 0x00; // 配置成 16MHz; 
}

/**********************************************************************
* 函数: Delay_Nms(u16 x)
* 功能: 延时Nms;
* 输入: int x; 
* 输出: 无
***********************************************************************/
void Delay_Nms(u16 x)
{
  u16 a,b;
  while(x--)
  {
    for(a=0;a<18;a++)
    {
      for(b=0; b<176; b++);  // 175->998us;  176->1.00425ms; 
    }    
  }
}

/**********************************************************************
* 函数: Delay_Nus(u16 x)
* 功能: 延时Nms;
* 输入: int x; 
* 输出: 无
***********************************************************************/
void Delay_Nus(u16 i)
{
  	u8 j;
 	while(i--)
 	{
 		for(j=0; j<3; j++)	  //10us基准延时程序 
 		{	
			;
 		}  
 	}
}

/*******************************************************************************
**函数名称:Init_TIM4()
**功能描述:定时器2 参数初始化
**入口参数:无
**输出:无
*******************************************************************************/
void Init_TIM4()
{ 
  	TIM4_IER_UIE = 0;           //先禁止定时器4更新中断
  	TIM4_EGR_UG = 0;            //
  	TIM4_PSCR_PSC = 7;          //定时器4时钟 = 16MHz / 128 = 125KHZ 
                                                           
  	TIM4_ARR = 125;             //设定1定时器产生1毫秒重装载时的计数值,255是最大值
  	TIM4_CNTR = 0x00;           //设定计数器的初值   
 
  	TIM4_SR_UIF = 0;            // 清除 更新中断标志
  	TIM4_SR_TIF = 0;            // 清除 触发中断标志
  	
  	TIM4_CR1_CEN = 1;           // 使能 定时器4
  	TIM4_CR1_ARPE = 1;          // 使能 预装载寄存器缓冲
  	
  	TIM4_IER_UIE = 1;           // 使能 更新 中断 
}

/**********************************************************************
* 函数: ADC_init(void)
* 功能: ADC2初始化流程“七步走”函数ADC_init(),无形参,无返回值
* 输入: 无;
* 输出: 无;
***********************************************************************/
void ADC_init(void)
{
  // 1.选择模拟通道,按需配置中断
  ADC_CSR = 0x04;         //选择通道 PD3-AIN4 ,禁止中断  PD3-AIN4 0000 0100
  
  // 2.配置分频系数,明确转换模式
  ADC_CR1 = 0x02;         //配置 预分频 为 fMaster/2,连续转换 模式 0 000 00 1 0
  
  // 3.配置触发事件,明确对齐方式
  ADC_CR2 = 0x08;         //禁止外部触发,数据 右对齐(先读低再读高)  0000 1000 
  //ADC_CR2=0x00;         //禁止外部触发,数据 左对齐(先读高再读低)
  
  // 4.初始配置模拟通道(无中断悬浮输入)
  PD_DDR_DDR3 = 0;         //配置PE6端口为输入模式
  PD_CR1_C13  = 0;         //配置PE6端口为悬浮输入模式
  PD_CR2_C23  = 0;         //配置PE6端口禁止外部中断
  
  // 5.按需禁止/使能施密特触发器功能
  ADC_TDRL= 0x00;           // 使能 斯密特 触发器
  
  // 6.使能 ADC 上电唤醒 并 禁用I/O输出功能
  ADC_CR1 |= 0x01;         // 首次将ADON位 置1 用于唤醒
  
  //7.启动ADC转换并获取转换数据
  //ADC_GET();             // 用户编写的ADC转换函数
}

/**********************************************************************
* 函数: ADC_GET(void)
* 功能: ADC2模数转换函数 ADC_GET(),无形参,无返回值
* 输入: 无;
* 输出: 无;
***********************************************************************/
void ADC_GET(void)
{
  	u8 num   = 0;		// 循环控制 变量,用于控制次数
  	ADC_CR1  = 0x02;	// 配置 预分频为 fMaster/2,连续转换模式
  	ADC_CR1 |= 0x01;	// 首次将 ADON位 置1 用于 唤醒
  	ADC_CR1 |= 0x01;	// 再次将 ADON位 置1 用于 启动ADC转换
  	
  	while(num < 10) 	// 采 10次 结果 (采集 10次 数据) 
  	{
	    while((ADC_CSR & 0x80) == 0);			// 待 ADC 转换 结束
	    
	    ADC_CSR &= 0x7F;						// 清除 ADC 转换完成标志位
	    
	    AD_Vtemp[num]  = (u16)ADC_DRL;			// 先将ADC转换数据低位赋值
	    AD_Vtemp[num] |= (u16)ADC_DRH << 8;  	// 再将左移8位后的高位数据与原低位数据进行或连接	    
	    										//(高位数据)+(低位数据)= 完整ADC采样数据结果
    	num ++;									// 循环控制变量自增
  	}
  	ADC_CR1 &= 0xFD; 							// 关闭ADC转换
}

/**********************************************************************
* 函数: ADC_GET(void)
* 功能: 平均值滤波函数AVG_AD_Vtemp(),无形参,无返回值
* 输入: 无;
* 输出: 无;
***********************************************************************/
void AVG_AD_Vtemp(void)
{
  	u8 i, j;								// 定义排序用内外层循环变量i和j
  	u16 temp;								// 定义中间“暂存”变量temp
  	for(i=10; i>=1; i--)					// 外层循环
  	{
    	for(j=0; j<(i-1); j++)				// 内层循环
    	{
      		if(AD_Vtemp[j] > AD_Vtemp[j+1])	// 数值比较 (排序) 
      		{
		        temp          =	AD_Vtemp[j];// 数值换位
		        AD_Vtemp[j]   = AD_Vtemp[j+1];
		        AD_Vtemp[j+1] =	temp;
	      	}
    	}
  	}
  	
  	for(i=2; i<=7; i++)			// 2,3,4,5,6,7 去掉2个最低去掉2个最高
  	{
  		AD_val += AD_Vtemp[i];	// 将 中间6个数值 累加
	}    	
    	
  	AD_val = (u16)(AD_val / 6);	// 累加和 求 平均值
}

/**********************************************************************
* 函数: main()
* 功能: 主函数
* 输入: 无;
* 输出: 无; 
***********************************************************************/
void main(void)
{  	
	asm("sim");  	// disable all interrupt  EA=0;  // 关闭 中断;
//	Init_GPIO(); 	// 设置 PA  PB 的初始状态; 
	Init_CLK();  	// 系统时钟初始化设置 16MHz;
	Init_TIM4(); 			// 调用 定时器4 初始化函数,通过定时器的 中断控制 来显示数码管	

	Init_NumericDisplay();	// 调用数码管驱动初始化函数,配置驱动芯片HC595对应IO口 
	ADC_init() ;
	   
  	asm("rim");   // 打开总中	

  	while(1)
	{
	  	ADC_GET();			// 获取 ADC 数据 采集; 
 		AVG_AD_Vtemp();  	// 取平均值; 
 		GET_voltage = (u16)(AD_val*4.882825);
 		AD_val = 0; // 清 0  ADC 转换 数据;
//		qian =  GET_vltage / 1000;
//		bei  = 	GET_vltage % 1000 / 100;
//		shi  = 	GET_vltage % 100 / 10;
//		ge  = 	GET_vltage % 10;
	}	
}


#pragma vector = 25     	//设置 定时器4 重载的中断向量号 = 25
__interrupt void Inter_TIM4(void)
{
  	TIM4_SR_UIF = 0;  		// 清除 中断标志
  	ms_count ++;           	// 中断使 ms_count++ 做加法,记录 1毫秒 产生的中断次数
  	
  	if(ms_count >= 2)     	// 2毫秒 点亮 一位 数码管 , 就是快速显示,等于 16毫秒 显示完 8个数码管,我们人眼 根本反应不过来,感觉是 8位数码管 同时显示
  	{
    	ms_count = 0;
	
		number[0] = GET_voltage / 1000; 		// 百位;
		number[1] = GET_voltage % 1000 / 100; 	// 十 位;
		number[2] = GET_voltage % 100 / 10; 		// 个 位;

		HC595_WriteData(~Data[number[SMGtimes]] , ~Wu[SMGtimes]);    //往数码管发送显示一个数码显示数据
				
		// 在 0,1,2 数据间 
		SMGtimes ++;     
		if(SMGtimes >= 3)    // 3位 数据 在 0, 1, 2位显示 
		{
		   	SMGtimes = 0 ;		 	
		}										 	
  	} 	
}









联系我们

联系人:客服在线

手机:全工:13903011251

电话:李R:13530006400

邮箱:729986191@qq.com

地址: GUANGDONG PROVINCE

用手机扫描二维码关闭
二维码