STC12C5A60S AD采样 5110显示 总是不对啊
/*-------------------------------------------------------------------------
C文件函数调用说明:
在main 加入头文件 #include"STC12C5A60S2.h" //加载AD 头文件
在main 主函数应初始化 Init_ADC();//初始化STC12C5A60S2 内部AD
ADC采用查询方式
uint ad_result; //定义一个 读取ad转换结果
ad_result=ADC_N(5,50); // P1^5 采集50次AD结果
需要注意问题:
实际电压值 :AD_Result=AD_Result*5/256; // 计算实际电压值
--------------------------------------------------------------------------*/
#include"STC12C5A60S2.h" //加载AD 头文件
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar code zifu[]={'0','1','2','3','4','5','6','7','8','9','.'};
uchar code voltage[]={"U = v"};
uchar a[5];
uchar num=123;
uchar vol=0;
uchar Vo;
sbit LCD_CLK = P2^0; //时钟
sbit SDIN = P2^1; //数据
sbit LCD_DC = P2^2; //1写数据,0写指令
sbit LCD_SCE = P2^3; //片选
sbit LCD_REST = P2^4; //复位,0复位
/*function
************************/
///////////SPI写操作
void LCD_write_byte(unsigned char dat, unsigned char command);
///////////5110初始化
void LCD_init(void);
///////////清屏
void LCD_clear(void);
//////////显示一个字符
void LCD_write_char(unsigned char c);
//////////显示字符串
void LCD_write_String(unsigned char X,unsigned char Y,unsigned char *s);
//ASCII码的字库
uchar code ASCII_6_8[][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 20 (空格)
,{0x00, 0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x00, 0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x00, 0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x00, 0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x00, 0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x00, 0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x00, 0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x00, 0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x00, 0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x00, 0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x00, 0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x00, 0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x00, 0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x00, 0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x00, 0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x00, 0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x00, 0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x00, 0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x00, 0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x00, 0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x00, 0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x00, 0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x00, 0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x00, 0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x00, 0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x00, 0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x00, 0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x00, 0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x00, 0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x00, 0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x00, 0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x00, 0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x00, 0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x00, 0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x00, 0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x00, 0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x00, 0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x00, 0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x00, 0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x00, 0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x00, 0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x00, 0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x00, 0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x00, 0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x00, 0x02, 0x04, 0x08, 0x10, 0x20} // 5c \ //
,{0x00, 0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x00, 0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x00, 0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x00, 0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x00, 0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x00, 0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x00, 0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x00, 0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x00, 0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x00, 0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x00, 0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x00, 0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x00, 0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x00, 0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x00, 0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x00, 0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x00, 0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x00, 0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x00, 0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x00, 0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x00, 0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x00, 0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x00, 0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x00, 0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x00, 0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x00, 0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x00, 0x10, 0x08, 0x08, 0x10, 0x08} // 7e ~
,{0x00, 0x78, 0x46, 0x41, 0x46, 0x78} // 7f (delete)
};
/*----------------------------
Software Delay_ADC function
----------------------------*/
void Delay_ADC(uint n)
{
uint x;
while (n--)
{
x = 5000;
while (x--);
}
}
void DelayMS(uint ms)
{
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
/*----------------------------
Get ADC result
----------------------------*/
uchar GetADCResult(uchar ch) //有参数输入 通道几 0-7 P1^0----P1^7
{
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;//0x00|0x00|ch|0x08:选择A/D输入通道,开始A/D转换
_nop_(); //Must wait before inquiry ,
_nop_(); //设置ADC_CONTR寄存器后需加4个CPU时钟周期的延时,才能保证值被写入ADC_CONTR寄存器
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
ADC_CONTR &= ~ADC_FLAG; //Close ADC
Vo=ADC_RES*5*10/256; //Return ADC result(为显示整数,这里将电压值扩大了十倍)
return Vo;
}
/*----------------------------
Initial ADC sfr
//P1^0 口为AD 输入
----------------------------*/
void Init_ADC()
{ //0000 0001
P1ASF = 0x01; //选择P1.0作为A/D输入通道
ADC_RES = 0; //Clear previous result // 清除AD转换结果寄存器之前的转换数据
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
Delay_ADC(2); //ADC power-on and Delay_ADC //初次打开ADC电源 要等待
}
/*------------函数说明--------------------------------
函数功能: 读取 计算平均值后的AD 结果
函数参数: chn:0-7 AD 通道 N :采集多少次AD 计算平均值
返回值 : ad值0-255 AD_Result=AD_Result*5/256; // 计算实际电压值
程序示例:
uint ad_result; //定义一个 读取ad转换结果
ad_result=ADC_N(5,50); // P1^5 采集50次AD结果
------------------------------------------------------*/
uchar ADC_N(uchar chn,uchar N) //采集N次然后取平均值 通道几 采集次数
{
unsigned char i;
unsigned int adc_tem=0;
for(i=N;i>0;i--)
{
adc_tem+=GetADCResult(chn);
}
adc_tem/=N; //adc_tem=adc_tem/N 赋值符合运算
return adc_tem; //返回
}
/***********************************************************
函数名称:LCD_write_byte
函数功能:模拟SPI接口时序写数据/命令LCD
入口参数:data :写入的数据;
command :写数据/命令选择;
出口参数:无
备 注:
***********************************************************/
void LCD_write_byte(unsigned char dat, unsigned char command)
{
unsigned char i;
LCD_SCE = 0; //5110片选有效,允许输入数据
if (command == 0) //写命令
LCD_DC = 0;
else
LCD_DC = 1; //写数据
for(i=0;i<8;i++) //传送8bit数据
{
if(dat&0x80)
SDIN = 1;
else
SDIN = 0;
LCD_CLK = 0;
dat = dat << 1;
LCD_CLK = 1; //时钟上升沿 写
}
LCD_SCE = 0; //关闭5110
}
/***********************************************************
函数名称:LCD_init
函数功能:5110初始化
入口参数:无
出口参数:无
备 注:
***********************************************************/
void LCD_init(void)
{
LCD_REST = 0; // 产生一个让LCD复位的低电平脉冲
_nop_();
LCD_REST = 1;
LCD_SCE = 0; // 关闭LCD
_nop_();
LCD_SCE = 1; //使能LCD
_nop_();
LCD_write_byte(0x21, 0); // LCD模式设置:芯片活动,水平寻址,使用扩展指令
LCD_write_byte(0xc8, 0); // 设置液晶偏置电压
LCD_write_byte(0x06, 0); // 温度校正
LCD_write_byte(0x13, 0); // 1:48
LCD_write_byte(0x20, 0); // 使用基本命令,V=0,水平寻址
LCD_clear(); // 清屏
LCD_write_byte(0x0c, 0); // 设定显示模式,正常显示
LCD_SCE = 0; //禁止LCD
}
/***********************************************************
函数名称:LCD_set_XY
函数功能:设置LCD坐标函数
入口参数:X :0-83 横坐标
Y :0-5 纵坐标
出口参数:无
备 注:
***********************************************************/
void LCD_set_XY(unsigned char X, unsigned char Y)
{
LCD_write_byte(0x80 | X, 0); // X 行(横坐标)
LCD_write_byte(0x40 | Y, 0); // column 列(纵坐标)
}
/*------------------------------------------
LCD_clear: LCD清屏函数
--------------------------------------------*/
void LCD_clear(void)
{
unsigned char t;
unsigned char k;
LCD_set_XY(0,0);
for(t=0;t<6;t++)
{
for(k=0;k<84;k++)
{
LCD_write_byte(0x00,1);
}
}
}
/***********************************************************
函数名称:LCD_write_char
函数功能:显示英文字符
入口参数:c : 显示的字符
出口参数:无
备 注:
***********************************************************/
void LCD_write_char(unsigned char c)
{
unsigned char line;
c-=0x20; //数组的行号 ASCII码减去 0x20
for (line=0; line<6; line++)
LCD_write_byte(ASCII_6_8[c][line], 1);
}
/*-------------------------------------------
;名称: 英文字符串显示函数
;参数:*s:英文字符串指针
---------------------------------------------*/
void LCD_write_String(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_set_XY(X,Y);
while (*s) //等效*s!='\0'
{
LCD_write_char(*s);
s++;
}
}
void display(uchar db) //液晶显示函数,用于显示模数转换后得到的数字量
{
float val;
val=db;
a[0]=(uchar)val/100;
a[1]=(uchar)val%100/10;
a[2]=10;
a[3]=(uchar)val%10;
LCD_set_XY(20,0);
LCD_write_char(zifu[a[0]]);
LCD_write_char(zifu[a[1]]);
LCD_write_char(zifu[a[2]]);
LCD_write_char(zifu[a[3]]);
DelayMS(1000);
}
void main()
{
LCD_init(); //定义一个 读取ad转换结果
Init_ADC();
while (1)
{
vol = ADC_N(0,1000); //采集50次然后取平均值 通道0(P1^0) 采集次数50
display(vol); //显示采集的电压值
LCD_write_String(0,0,voltage);
}
}
H 文件如下
/******************************************************************
ADC头文件:
//
函数调用说明:
在main 加入头文件 #include"STC12C5A60S2.h" //加载AD 头文件
在main 主函数应初始化 Init_ADC(); //Init ADC sfr
********************************************************************/
#ifndef __STC12C5A60S2_H__
#define __STC12C5A60S2_H__ //防重复包含语句
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/*Declare SFR associated with the ADC */
sfr ADC_CONTR = 0xBC; //ADC control register 声明ADC 控制寄存器
sfr ADC_RES = 0xBD; //ADC high 8-bit result register ADC 转换结果寄存器 高位
sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register ADC 转换结果寄存器 低位
sfr P1ASF = 0x80; //P1 secondary function control registerP1模拟功能控制寄存器
sfr AUXR1 = 0x8A;
/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks
void Delay_ADC(uint n); //延时
void Init_ADC(); //初始化
uchar GetADCResult(uchar ch); //有参数输入 通道几 0-7 P1^0----P1^7
uchar ADC_N(uchar chn,uchar N); //采集N次然后取平均值 通道几 采集次数
#endif //防重复包含语句 结束
先看一下是显示的东西不对还是显示的值不对,学会debug
仿真下,看看从ADC出来的值对不对,对的话就是显示的问题,不对的话就是ADC处理的问题。
不溢出才怪呢!
程序示例:
uint ad_result; //定义一个 读取ad转换结果
ad_result=ADC_N(5,50); // P1^5 采集50次AD结果
------------------------------------------------------*/
uchar ADC_N(uchar chn,uchar N) //采集N次然后取平均值 通道几 采集次数
{
unsigned char i;
unsigned int adc_tem=0;
for(i=N;i>0;i--)
{
adc_tem+=GetADCResult(chn); /*假设每次采样值都为256 ,那么50次累加值为 50*256 = 12800,没有溢出(int 型 为 65536 )*/
}
adc_tem/=N; //adc_tem=adc_tem/N 赋值符合运算
return adc_tem; //返回
}
那么问题就来了,到底哪里出错了呢?
你的
main()
{
ADC_N(0,1000) ; //这一句绝对出错,为什么?因为 1000*256 = 256000 >>65536 ,不出错才怪,建议还是改用50,或者把adc_tem定义为 long
}