/*******************************************************************************/
// 功能:模拟信号 转 数字信号 (电压采集)
/*******************************************************************************/
// 头文件 宏定义
#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