stc12C5A60S2内部AD应用

合集下载

STC12C5A60S2各模块的应用分享大家

STC12C5A60S2各模块的应用分享大家

STC12C5A60S2各模块的应用分享大家/*****************串口应用******************/ ///////////////////串口一//////////////#include"12c5a60s2.h"#include"uart.h"unsignedcharbuf[3],g;voidinitUart(){EA=1;BRT=0XFD;//独立波特率发生器9600AUXR=0X11;//启动独立波特率发生器,12分频// TMOD=0X20;//用定时器1做波特率发生器//TH1=0XFD;//TL1=0XFD;//TR1=1;REN=1;SM1=1;ES=1;g=0;}voidsendDate(unsigned char date){SBUF=date;while(!TI);TI=0;}void work(){sendDate(buf[0]); sendDate(buf[1]);}voidres()interrupt 4{buf[g++]=SBUF;if(g>;=2){g=0;work();}while(!RI);RI=0;}////////////////////串口二//////////////// #include;#include"uart2.h"#defineS2TI 0X02//不能位寻址#defineS2RI 0X01//不能位寻址unsigned charshuzhi;voidinitUART2(){BRT=0XFD;//定初值9600AUXR=0X11;//使用波特率独立发生器 12分频 9600 //AUXR=0X19;//使用波特率独立发生器 1分频 19200 EA=1;IE2=0X01;//ES2=1;S2CON=0X50;//S2REN=1;S2SM1=1;}voidsenddate(unsigned char date){S2BUF=date;//判断是否是一if(S2CON&S2TI)//清零S2CON&=~S2TI;}void uart2r()interrupt 8{if(S2CON&S2RI)//判断是否是一{S2CON&=~S2RI;//清零shuzhi=S2BUF;senddate(0x40);}}/******************AD转换*************************/#include"12c5a60s2.h"#include"12c5aad.h"#include;//寄存器地址声明,有12c5a60s2 头文件可省略//sfr ADC_CONTR =0XBC;//sfr ADC_RES =0XBD;//sfr ADC_ERSL =0XBE;//sfr P1ASF =0X9D;//宏定义#define ADC_POWER 0X80// ad电源控制位#define ADC_FLAG0x10//ad转换结束标志位#define ADC_START0x08//ad转换开始控制位#define ADC_SPEEDLL 0x00 //540 转换速率#define ADC_SPEEDL 0x20 //360 转换速率#define ADC_SPEEDH 0x40 //180 转换速率#define ADC_SPEEDHH 0x60 //90 转换速率//ad转换延时函数voiddelayad(unsignedint z){unsignedintx,y;for(x=5000;x>;0;x--)for(y=z;y>;0;y--);}//ad初始化函数voidinitad(){P1ASF=0XFF;//设置P1口为ad转换模式ADC_RES=0;//ad转换结果寄存器清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL; //打开ad转换电源,最慢频率delayad(2);//延时待电源稳定提高精确性}unsignedchar getAD(unsigned char ch) //ch通道选择{ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|ch ; _nop_(); _nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FLAG));//ad转换完成 FALG 为1ADC_CONTR&=~ADC_FLAG;//FALG置置零return ADC_RES;}/********************PCA/PWM*****************/ /////////////////////中断模式/////////////////////#include;#include"pcaint.h"unsigned charmiao;voidinitPCAint(void){CCON=0;CL=0;CH=0;CMOD=0X00;//禁止CF中断CCAPM0=0X11;// (CAPN0 负捕获,CAPP0 正捕获)本模块负捕获CCAPM1=0X21; // 模块一正捕获CR=1;//开计数列阵EA=1;//开总中断}voidpca()interrupt7{if(CCF0==1){CCF0=0;//清零模块中断标志位miao++;}if(CCF1==1){CCF1=0;//清零模块中断标志位miao--;}}//////////////////////////定时器模式////////////////////#include;#include"pcatime.h" unsignedint value;//数组赋值unsigned char ptime;//ptime=0xb402;50ms定时 0x2400 10ms voidinitPCATime(){CCON=0X00;//标志位清零CL=0;//pca L列阵清零CH=0;//PCA H列阵清零CMOD=0X00;//选择时钟模式CCAP1L=value;//先赋值高位CCAP1H=value>;>;8; //赋值CCAPM1=0X49;//允许比较器ECOM1,MAT1、ECCF1置位允许CCF1中断CR=1;//允许列阵EA=1;//开总中断}voidpcatime()interrupt 7//两个PCA模块都是中断7 {unsignedint i;CL=0;//清零不然是溢出时钟,定时无效 CH=0;//清零不然是溢出时钟,定时无效 CCF1=0;CCAP1L=value;CCAP1H=value>;>;8;i++;if(i>;=20){i=0;ptime++;}}///////////////////////PWM模式//////////////////////#include"12c5a60s2.h" #include"12c5apwm.h" voidinitPWM(void ){CCON=0;//关闭PCA计数及标志位清零CL=0;// 清空pca计数低位CH=0;// 清空pca计数高位CMOD=0X08;// 用系统时钟不分频//CCAP0H=CCAP0L=0x01;// 模块0复初值CCAPM0=0X42;//允许模块0比较器工作,脉宽调制模式//CCAP1H=CCAP1L=0X01;//模块1复初值CCAPM1=0X42;//允许模块1比较器工作,脉宽调制模式CR=1;//启动pca计数}void tiaoj(unsignedchar pwmH,unsigned char pwmL){CCAP0H=CCAP0L=pwmH;// 模块0复值CCAP1H=CCAP1L=pwmL;// 模块1复值}/**********************EEPROM******************** *****/#include;#include;#include"eeporm.h"#defineRdeeprom 0x01#defineWreeprom 0x02#defineERSeeprom 0x03#defineWTime0x01 // 0x02 0x03 0x00sfr ISP_DATA=0Xc2;sfr ISP_ADDRH=0Xc3;sfr ISP_ADDRL=0Xc4;sfr ISP_CMD=0Xc5;sfr ISP_TRIG=0Xc6;sfr ISP_CONTR=0Xc7;unsigned char miao,miao2,miao3;bit int0flag;void ISP_Open(void){EA=0;//关中断ISP_CONTR=ISP_CONTR&0X18;//清零ISP_CONTR=ISP_CONTR|WTime;//等待时间ISP_CONTR=ISP_CONTR|0x80;//使能ISP}void ISP_Close(void){ISP_CONTR=ISP_CONTR&0X7F; //停止ISP使能ISP_TRIG=0X00;//命令触发寄存器清零EA=1;//开中断}void ISP_Goon(void){//打开ISPISP_Open();ISP_TRIG=0x5a;//写触发命令ISP_TRIG=0xa5;//写触发命令_nop_();//等待}voidbyte_write(unsigned int add,unsigned char dat) //写某地址数据{ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=(unsignedchar)(add&0x00ff);//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|Wreeprom;//写命令ISP_DATA=dat;//读写寄存器赋值ISP_Goon();//打开、触发ISP_Close();_nop_();//关闭}voidsector(unsigned int add) {ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=0x00;//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|ERSeeprom;//删命令ISP_Goon();//打开、触发ISP_Close();_nop_();}unsignedchar byte_read(unsigned int add) {ISP_ADDRH=(unsignedchar)(add>;>;8);//地址高位ISP_ADDRL=(unsignedchar)(add&0x00ff);//地址低位ISP_CMD=ISP_CMD&0XF8;//命令模式复位ISP_CMD=ISP_CMD|Rdeeprom;//读命令ISP_Goon();//打开、触发ISP_Close();_nop_();return (ISP_DATA);}voidinitc(){IT0=1;EX0=1;EA=1;}voidint0()interrupt 0{if(int0flag==1){EA=0;sector(0x00ff); //0000h-03ffh byte_write(0X00ff,miao3);EA=1;}}///////////////////////////////////////////////// ////////写的一般,不足之处还望包涵,均测试通过,欢迎提好的建议。

STC12C5A60S2的ADC PWM功能

STC12C5A60S2的ADC PWM功能

STC12C5A60S2的ADC+PWM功能STC12C5A60S2单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度可达到250 KHz(25万次/秒)。

脉宽调制(PWM)是一种使用程序来控制波形占空比、周期、相位波形的技术。

STC12C5A60S2单片机的PAC模块可以通过程序设定,使其工作于8位PWM模式。

下面是一段将ADC和PWM结合起来应用的程序:/************************************************ ***************时间:2012.12.1晶振:12MHz功能描述:AD采集电位器的电压信号,然后信号以PWM 信号输出控制LED的亮度(调节电位器)当电位器两端的电压大时,LED较亮,同时用1602显示采集的电压值AD采集通道:P1.0PWM输出: P1.3************************************************* **************/#include;#include;unsigned int result,ge,shifen,baifen;unsigned charseg[10]={'0','1','2','3','4','5','6','7','8','9'} ;//要显示字符sbit RS = P2^4; //命令数据sbit RW = P2^5; //写还是读sbit EN = P2^6; //使能端#define RS_CLR RS=0#define RS_SET RS=1#define RW_CLR RW=0#define RW_SET RW=1#define EN_CLR EN=0#define EN_SET EN=1#define DataPort P0/*------------------------------------------------uS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时长度如下 T=tx2+5 uS------------------------------------------------* /void DelayUs2x(unsigned char t){while(--t);}/*------------------------------------------------mS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------* /void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/*------------------------------------------------判忙函数------------------------------------------------* /bit LCD_Check_Busy(void){DataPort= 0xFF;RS_CLR;RW_SET;EN_CLR;_nop_();EN_SET;return (bit)(DataPort & 0x80);}/*------------------------------------------------写入命令函数------------------------------------------------*/void LCD_Write_Com(unsigned char com){while(LCD_Check_Busy()); //忙则等待RS_CLR;RW_CLR;EN_SET;DataPort= com;_nop_();EN_CLR;}/*------------------------------------------------写入数据函数------------------------------------------------* /void LCD_Write_Data(unsigned char Data){while(LCD_Check_Busy()); //忙则等待RS_SET;RW_CLR;EN_SET;DataPort= Data;_nop_();EN_CLR;}/*------------------------------------------------清屏函数------------------------------------------------* /void LCD_Clear(void){LCD_Write_Com(0x01);DelayMs(5);}/*------------------------------------------------写入字符串函数------------------------------------------------* /void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s){{LCD_Write_Com(0x80 + x); //表示第一行}else{LCD_Write_Com(0xC0 + x); //表示第二行}while (*s){LCD_Write_Data( *s);s ++;}}/*------------------------------------------------写入字符函数------------------------------------------------* /void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data){{LCD_Write_Com(0x80 + x);}else{LCD_Write_Com(0xC0 + x);}LCD_Write_Data( Data);}/*------------------------------------------------LCD初始化函数------------------------------------------------* /void LCD_Init(void){LCD_Write_Com(0x38); /*显示模式设置*/DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);LCD_Write_Com(0x08); /*显示关闭*/LCD_Write_Com(0x01); /*显示清屏*/LCD_Write_Com(0x06); /*显示光标移动设置*/ DelayMs(5);LCD_Write_Com(0x0C); /*显示开及光标设置*/ }/*------------------------------------------------ADC初始化函数------------------------------------------------* /void InitADC(){P1ASF =0x01;//使能P1口ADC功能ADC_RES = 0;ADC_CONTR = 0xc8;}/*------------------------------------------------主函数------------------------------------------------* /void main(void){LCD_Init();LCD_Clear();//清屏LCD_Write_String(5,0,"526lab");//(列,行,数据)LCD_Write_String(2,1,"Result:"); InitADC();IE=0xa0;//开中断while (1){//PWM初始化CCON=0;CMOD=0;//1MCCAP0H=CCAP0L=ADC_RES;CCAPM0=0x42;//开启PWMCR=1;//计时开始//调用显示LCD_Write_Char(9,1,seg[ge]);LCD_Write_Char(10,1,'.');LCD_Write_Char(11,1,seg[shifen]);LCD_Write_Char(12,1,seg[baifen]);LCD_Write_Char(13,1,'V');}}/*------------------------------------------------ADC中断处理函数------------------------------------------------* /void adc_isr() interrupt 5 using 1{unsigned int temp;temp=ADC_RES;result=temp*0.01953125*1000;ge=result/1000;shifen=result%1000/100;baifen=result%100/10;ADC_CONTR = 0xc8;//开启转换}12C5A60S2.h的头文件//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机内核特殊功能寄存器 C51 Core SFRs// 7 6 5 4 3 2 1 0Reset Valuesfr ACC = 0xE0; //Accumulator 0000,0000sfr B = 0xF0; //B Register 0000,0000sfr PSW = 0xD0; //Program Status Word CY AC F0 RS1 RS0 OV F1 P 0000,0000//-----------------------------------sbit CY = PSW^7;sbit AC = PSW^6;sbit F0 = PSW^5;sbit RS1 = PSW^4;sbit RS0 = PSW^3;sbit OV = PSW^2;sbit P = PSW^0;//-----------------------------------sfr SP = 0x81; //Stack Pointer 0000,0111sfr DPL = 0x82; //Data Pointer Low Byte0000,0000sfr DPH = 0x83; //Data Pointer High Byte 0000,0000//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机系统管理特殊功能寄存器// 7 6 5 4 3 2 1 0 Reset Valuesfr PCON = 0x87; //Power Control SMOD SMOD0 LVDF POF GF1 GF0 PD IDL 0001,0000// 7 6 5 4 3 2 1 0Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS0000,0000//-----------------------------------sfr AUXR1 = 0xA2; //Auxiliary Register 1 - PCA_P4 SPI_P4 S2_P4 GF2 ADRJ - DPS 0000,0000 /*PCA_P4:0, 缺省PCA 在P1 口1,PCA/PWM 从P1 口切换到P4 口: ECI 从P1.2 切换到P4.1 口,PCA0/PWM0 从P1.3 切换到P4.2 口PCA1/PWM1 从P1.4 切换到P4.3 口SPI_P4:0, 缺省SPI 在P1 口1,SPI 从P1 口切换到P4 口: SPICLK 从P1.7 切换到P4.3 口MISO 从P1.6 切换到P4.2 口MOSI 从P1.5 切换到P4.1 口SS 从P1.4 切换到P4.0 口S2_P4:0, 缺省UART2 在P1 口1,UART2 从P1 口切换到P4 口: TxD2 从P1.3 切换到P4.3 口RxD2 从P1.2 切换到P4.2 口GF2: 通用标志位ADRJ:0, 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器1,10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器DPS: 0, 使用缺省数据指针DPTR01,使用另一个数据指针DPTR1//-----------------------------------sfr WAKE_CLKO = 0x8F; //附加的 SFR WAK1_CLKO/*7 6 5 4 3 2 1 0 Reset ValuePCAWAKEUP RXD_PIN_IE T1_PIN_IE T0_PIN_IE LVD_WAKE _ T1CLKO T0CLKO 0000,0000Bb7 - PCAWAKEUP : PCA 中断可唤醒 powerdown。

STC12c5a60s2官方手册AD程序(中文注释)

STC12c5a60s2官方手册AD程序(中文注释)
sfr ADC_CONTR = 0xBC; //ADC控制寄存器
sfr ADC_RES = 0xBD; //ADC的高8位结果寄存器
sfr ADC_LOW2 = 0xBE; //ADC的低2位结果寄存器
sfr P1ASF = 0x9D; //P1辅助功能控制寄存器
/*ADC操作定义常量*/
#define ADC_SPEEDL 0x20 //360 clocks
#define ADC_SPEEDH 0x40 //180 clocks
#define ADC_SPEEDHH 0x60 //90 clocks
void InitUart();
void SendData(BYTE dat); void Delay(WORD n);
}
/*----------------------------
Uart初始化
----------------------------*/
void InitUart()
{
SCON = 0x5a; //8位数据,无校验位
TMOD = 0x20; //T1为8位自动重载
void InitADC( )
{
P1ASF = 0xff; //设置所有P1为模拟输入端口
ADC_RES = 0; //清除先前的结果
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
Delay(2); //ADC 延迟启动和启动/转换的电源
while (1);
}
/*----------------------------
ADC函数中断服务例程

stc12c5a60s2 AD 程序

stc12c5a60s2  AD 程序
//AD速度设置。
#define ADC_SPEEDLL 0x00 //540 clocks
#define ADC_SPEEDL 0x20 //360 clocks
#define ADC_SPEEDH 0x40 //180 clocks
#define uchar unsigned char
#define uint unsigned int
/*LCD 各种端口的设置 */
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
sbit LCD_PSB=P2^3;
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //ADC开始标志位。
/*可写入 4*8 汉字,x的范围是1到4,y的范围是1到8*/
void lcd_string(uchar x,uchar y,char*str)
{
static uchar flag = 0;
uchar i = 0;
if(!flag)
{
lcd_init();
flag = 1;
case 3 : temp = 0x88;
break;
case 4 : temp = 0x98;
break;
default : temp = 0x80;
break;
}
pos = temp + col-1;
LCD_0(0,pos);
}
}
/*字符位置的选定*/

用STC12C5A60S2测试AD转换程序

用STC12C5A60S2测试AD转换程序

刚到手一块STC12C5A60S2单片机,看说明文档里有AD转换功能。

于是写了这段程序测试学习一下,程序在我的学习板上运行稳定,如里要你只要改下I/O口即可。

里面注解挺详细的,愿对看文档的人有所帮助吧。

下面是主程序部份:# include <stc12c5a60s2.h># include <intrins.h># define uchar unsigned char# define uint unsigned int/* -------------函数声明开始--------------- */void delay_ms(uchar ms);//延时函数void init_adc(void); //初始化ADuint get_adc(void); //获取AD结果,返回UINT型值。

extern write1602_3b (uchar pos, uint n);extern void init_1602 ();/* -------------函数声明结束--------------- */void init_adc(void){P1ASF = 0x01; //AD功能寄存器,设置I/O口作为AD转换实用。

使用P1.0口。

ADC_RES = 0; //清理结果寄存器的值ADC_RESL = 0; //清理结果寄存器的值ADC_CONTR = 0x80; //开启AD电源并设置转换周期为540个时钟周期转换一次。

//ADC_POWER=1;CHS2,1,0为0,用p1.0作为输入。

SPEED1,0为0,540个时钟,delay_ms(2);}void delay_ms(uchar ms){uint i = 5000;while(ms--){while(i--);}}uint get_adc(void){uint d=0;ADC_CONTR = 0X88;_nop_();_nop_();_nop_();_nop_();while(!(ADC_CONTR & 0X10));ADC_CONTR &= ~0X10;d |= ADC_RES;d <<= 2;d |= ADC_RESL;return d;}void main (void){uint v=0;uint dat = 0;// P2M0 = 0X00;// P2M1 = 0XFF;_nop_();_nop_();_nop_();_nop_();_nop_();init_1602 ();init_adc();while(1){dat=get_adc();v = (uint)((dat*5.0*100)/1024);write1602_3b (0x48,v);delay_ms(10);}}下面是1602显示部分,在编译时要把两个程序都放入KEIL工程里。

stc12c5a60s2_AD采集_12864串行显示终极程序_带滤波

stc12c5a60s2_AD采集_12864串行显示终极程序_带滤波

stc12c5a60s2 AD采集12864串行显示终极程序带滤波作者:电子工程师(天津)由于AD采集电压并在12864上显示的程序很常用,然而网上很多程序各种各样,又有很多缺点,所以就利用工作之余的时间对用到的程序进行了整理,调试,优化以方便各位电子爱好者使用。

这段程序已经调试通过,改下io即可直接应用。

最后有两张效果图。

LCD_PSB=0;(并串选择口)LCD_RST =1;(复位口)注意:本程序用的是12864串行显示,将PSB引脚接地,RST拉高、片选口RS接高之后除了电源和地线,只用2根线就可以显示了,接线很方便,最大程度的节省了io口。

本程序是以电流采集为例的,采集的是电流传感器输出的电压,然后转换成电流,如果只需要采集电压的话将转化为电流的语句删除即可。

AD是stc12c5a60s2 自带的10位AD。

使用很方便。

有不明白的可以qq联系我,1264136841#include"stc12c5a60s2.h"#include"intrins.h"float ADvalue = 0;unsigned int volage = 0;unsigned int current = 0;void InitializeDisplay();void InitializeLcd12864();void displaystring(unsigned char add,unsigned int num);void WriteCommandLcd12864(unsigned char temp);void InitializeDisplay();void InitializeAD();unsigned int ReadADvalue(unsigned char channel);float SmoothingFilter(unsigned int temp);void Delay_us(unsigned int xus);void Delay_ms(unsigned int xms);sbit LCD_SID = P2^5;//即RW口sbit LCD_CLK = P2^6;//即E口code unsigned char name1[] = {"escrewdriver"};code unsigned char name2[] = {"电流采集显示"};code unsigned char name3[] = {"电流: A "};code unsigned char name4[] = {"参数:mm "};"};void main(){// InitializeAD();// InitializeTimer0();// InitializeUart();InitializeLcd12864();InitializeDisplay();while(1){ADvalue = ReadADvalue(0); //读回AD值ADvalue = ADvalue*5000/1024; //转换成电压值/* if(ADvalue > 2500) //防止电压浮动在2.5V以上ADvalue = 2500;ADvalue = 2500-ADvalue; //电流反方向流过传感器,输出电压值小于2.5V,*/current = (ADvalue*8); //计算电流,每0.625V代表7.5A 即每1V代表12Acurrent = SmoothingFilter(current); //进行一下平滑滤波displaystring(0x8b,current);displaystring(0x9b,0.5*current);}}/*********************延时函数******************************/void Delay_us(unsigned int xus) //@11.0592MHz{while(xus-->0){_nop_();_nop_();_nop_();}}void Delay_ms(unsigned int xms) //@11.0592MHz{unsigned int y=0;for(;xms>0;xms--)for(y=0;y<600;y++);}/*******************延时函数*****************************//*******************************************************//********************lcd12864显示部分*******************//*******************************************************/void InitializeLcd12864()WriteCommandLcd12864(0x30);//基本功能WriteCommandLcd12864(0x0c);//显示开,光标关WriteCommandLcd12864(0x01);//清屏}void WriteByteLcd12864(unsigned char temp){unsigned char i;LCD_CLK = 0;for(i=0;i<8;i++){if(temp&0x80)LCD_SID = 1;elseLCD_SID = 0;LCD_CLK = 1;Delay_us(10);temp <<= 1;LCD_CLK = 0;Delay_us(10);}}void WriteCommandLcd12864(unsigned char temp){WriteByteLcd12864(0xf8);WriteByteLcd12864(temp&0xf0);WriteByteLcd12864(temp<<4);}void WriteDataLcd12864(unsigned char temp){WriteByteLcd12864(0xfa);WriteByteLcd12864(temp&0xf0);WriteByteLcd12864(temp<<4);}void WriteStringAddress(unsigned char add,unsigned char length,unsigned char *temp) {WriteCommandLcd12864(add);for(;length>0;length--){WriteDataLcd12864(*temp);temp++;}/***显示电压和电流***/void displaystring(unsigned char add,unsigned int num){unsigned char buf[10],i;buf[0] = num/10000;buf[1] = num%10000/1000;buf[2] = num%1000/100;buf[3] = num%100/10;buf[4] = num%10;WriteCommandLcd12864(add);for(i=0;i<5;i++){WriteDataLcd12864(buf[i]+0x30);if(i == 1) WriteDataLcd12864('.');}}/***显示内容初始化***/void InitializeDisplay(){WriteStringAddress(0x81,12,name1);WriteStringAddress(0x91,12,name2);WriteStringAddress(0x88,16,name3);WriteStringAddress(0x98,16,name4);Delay_ms(100);// WriteStringAddress(0x98,6,name5);}/********************lcd12864显示部分*******************/ /*******************************************************//*******************************************************/ /********************AD采集部分*************************/ /*******************************************************/ /***AD初始化***/void InitializeAD(){P1ASF=0xff ; //P1口全部作为模拟功能AD使用ADC_RES=0; //清零转换结果寄存器高8位ADC_RESL=0; //清零转换结果寄存器低2位ADC_CONTR=0x80;//开启AD电源Delay_ms(1); //等待1ms,让AD电源稳定}/***读对应通道AD值***/unsigned int ReadADvalue(unsigned char channel){ADC_CONTR=0x88|channel; //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0_nop_();_nop_();_nop_();_nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器while(!(ADC_CONTR&0x10)); //等待转换完成ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)}/***实时平滑滤波***/float SmoothingFilter(unsigned int temp){static unsigned int i=0;static unsigned int buf[10];float average = 0;if(i>=10)i=0;buf[i++] = temp;average = (average+buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]+buf[8]+buf[9])/10;return average;}/*******************************************************//*******************************************************/。

STC12C5A60S2自带10位AD测量电压值LCD1602显示(C程序)

STC12C5A60S2自带10位AD测量电压值LCD1602显示(C程序)

/*---—-——————----—--------—----—---————-------—--————-—-—-—-—----——————-———--——---———--—————-—--——--—---——-—-—---———-——————-—*//*--************************功能【AD转换,液晶显示】**************************——*//*——************************芯片:【STC12C5A60S2】******************************-—*//*-—************************液晶:【LCD1602】***********************************-—*//*-—************************ADC管脚:【P1。

0~P1.7 】***************************——*//*--************************检测范围:【0。

00~4.99V】***************************——*//*—-——-—-—--———-—————-——--———---—----—-—-—---——————---————-——-—-—----—-—------—--———-——--——-—————-—-———-—---———--—--————--—-—*/#include "reg52。

h"#include "intrins。

h"typedef unsigned char uchar;typedef unsigned int uint;#define _Nop() _nop_()/*—-——--—--—-—--——-—-—----以下为LCD1602显示模块定义—--———--—-——-—--——————-*/unsigned char data_char_table[]= {”0123456789ABCDEF”};//LCD数据unsigned char Lcd_Dis1_table[] = {”Position:No。

STC12C5A60S2单片机实现AD采样并液晶显示(数字燃油表)

STC12C5A60S2单片机实现AD采样并液晶显示(数字燃油表)

数字燃油表模拟电路设计可实现以下功能:1、推动滑动变阻器,能使LCD从0显示到1002、档显示数字低于10时,灯亮,LCD显示“oil low”以下为C程序:#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}sbit LED=P1^0;sbit LCD_RS=P2^6;sbit LCD_RW=P2^5;sbit LCD_EN=P2^7;sbit SCL=P2^0; //I2C时钟引脚sbit SDA=P2^1; //I2C数据输入输出引脚uchar Recv_Buffer[4]; //数据接收缓冲uint Voltage[]={'0','0','0','0'}; //数据分解为电压x.xxbit bdata IIC_ERROR; //I2C错误标志位uchar LCD_Line_1[]={" "};//延时void delay(int ms){uchar i;while(ms--) for(i=0;i<250;i++) Delay4us();}//LCD忙检测bit LCD_Busy_Check(){bit Result;LCD_RS=0;LCD_RW=1;LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);LCD_EN=0;return Result;}//写指令void LCD_Write_Command(uchar cmd){while(LCD_Busy_Check());LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();P0=cmd;Delay4us();LCD_EN=1;Delay4us();LCD_EN=0;}// 写数据void LCD_Write_Data(uchar dat){while(LCD_Busy_Check());LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;Delay4us();LCD_EN=1;Delay4us();LCD_EN=0;}//初始化void LCD_Initialise(){LCD_Write_Command(0x38);delay(5);LCD_Write_Command(0x0c);delay(5);LCD_Write_Command(0x06);delay(5);LCD_Write_Command(0x01);delay(5);}//设置显示位置void LCD_Set_Position(uchar pos){LCD_Write_Command(pos|0x80);}//显示一行void LCD_Display_A_Line(uchar Line_Addr,uchar s[]){uchar i;LCD_Set_Position(Line_Addr);for(i=0;i<16;i++)LCD_Write_Data(s[i]);}// 将模数转换后得到的值分解存入缓存void Convert_To_Voltage(uchar val){uchar Tmp; //最大值为255,对应100L,255/100=2.55 val=val*0.393;Voltage[2]=val/100+'0'; //Tmp=val%100; //Voltage[1]=Tmp/10+'0';Tmp=Tmp%10;Voltage[0]=Tmp+'0';}//启动I2C总线void IIC_Start(){SDA=1;SCL=1;Delay4us();SDA=0;Delay4us();SCL=0;}//停止I2C总线void IIC_Stop(){SDA=0;SCL=1;Delay4us();SDA=1; Delay4us();SCL=0;}// 从机发送应答位void Slave_ACK(){SDA=0;SCL=1;Delay4us();SCL=0;SDA=1;}// 从机发送非应答位void Slave_NOACK(){SDA=1;SCL=1;Delay4us();SCL=0;SDA=0;//发送一字节void IIC_SendByte(uchar wd){uchar i;for(i=0;i<8;i++) //循环移入8位{SDA=(bit)(wd&0x80);_nop_();_nop_();SCL=1;Delay4us();SCL=0;wd<<=1;}Delay4us();SDA=1; //释放总线并准备读取应答SCL=1;Delay4us();IIC_ERROR=SDA; //IIC_ERROR=1表示无应答SCL=0;Delay4us();}//接收一字节uchar IIC_ReceiveByte(){uchar i,rd=0x00;for(i=0;i<8;i++){SCL=1;rd<<=1;rd|=SDA;Delay4us();SCL=0;Delay4us();}SCL=0;Delay4us();return rd;}//连续读入4路通道的A/D转换结果并保存到Recv_Buffervoid ADC_PCF8591(uchar CtrlByte){uchar i;IIC_Start();IIC_SendByte(0x90); // 发送写地址if(IIC_ERROR==1)return;// IIC_SendByte(CtrlByte); //发送控制字节//if(IIC_ERROR==1)return;IIC_Start(); //重新发送开始命令IIC_SendByte(0x91); // 发送读地址if(IIC_ERROR==1)return;IIC_ReceiveByte(); //空读一次,调整读顺序Slave_ACK(); //收到一字节后发送一个应答位for(i=0;i<4;i++)Recv_Buffer[i++]=IIC_ReceiveByte();Slave_ACK(); //收到一个字节后发送一个应答位}Slave_NOACK();IIC_Stop(); //收到一个字节后发送一个非应答位}// 向PCF8591发送1字节进行AD转换//主程序void main(){LED=0;LCD_Initialise();while(1){ADC_PCF8591(0x04);if(Recv_Buffer[0]<26){LCD_Display_A_Line(0x00, "Oil Low! ");LED=1;}else{Convert_To_Voltage(Recv_Buffer[0]);LCD_Line_1[2]=Voltage[2];LCD_Line_1[3]=Voltage[1];LCD_Line_1[4]=Voltage[0];LCD_Display_A_Line(0x00, LCD_Line_1);LED=0;}delay(50);}}如有侵权请联系告知删除,感谢你们的配合!。

STC12C5A60S2-AD电压高级采集

STC12C5A60S2-AD电压高级采集

STC12C5A60S2-AD电压高级采集/*使用STC单片机内置10AD(仅用高八位,分辨率为5mV)做的简易电压表*//*本程序AD部分使用了深圳宏晶公司官方AD转换示范程序修改, 特此鸣谢*//*使用STC12C5A60S2 1T单片机,12M外部晶振,Keil V3编译通过,AD转换脚定义为P1.1, *//*使用芯片本身5V电源为基准,在深圳精创电子的51/AVR开发板实现。

8位共阳LED字符码*//*接P0口,位线接在P2口,均为低电平显示,使用右4位。

本显示程序摘自网上,一并感谢。

*//*----2010.07.04 written by autopccopy() */#include <intrins.H>#include <stc12c5a60s2.H> //STC的新头文件0X6D,/*5*/0X7D,/*6*/0X07,/*7*/0X7F,/*8*/0X6F,/*9*/0xFF};void led(int n) //数码管显示及数据处理程序{P0 = 0xFF;P0 = DATA_LED[n % 10]; //个位P20 = 0;delay(1);P20 = 1;P0 = 0xFF;P0 = DATA_LED[n / 10 % 10]; //十位P21 = 0;delay(1);P21 = 1;P0 = 0xFF;P0 = DATA_LED[n / 100 % 10]; //百位 P22 = 0;delay(1);P22 = 1;P0 = 0xFF;P0 = DATA_LED[n / 1000 % 10]; //千位 P23 = 0;P07=0; //千位显示小数点delay(1);P23 = 1;}//---------------------------------------------------------------------INT8U get_AD_result(INT8U channel) //AD 转换部分{INT8U AD_finished=0; //存储 A/D 转换标志ADC_RES = 0; //高八ADC_RESL = 0; //低二位(本例未使用)channel &= 0x07; //0000,0111 清0高5位ADC_CONTR = AD_SPEED;_nop_();ADC_CONTR |= channel; //选择A/D 当前通道_nop_();ADC_CONTR |= 0x80; //启动A/D 电源delay(1); //使输入电压达到稳定ADC_CONTR |= 0x08; //0000,1000 令 ADCS = 1, 启动A/D转换,AD_finished = 0;while (AD_finished ==0 ) //等待A/D转换结束{AD_finished = (ADC_CONTR & 0x10);//0001,0000 测试A/D转换结束否ADC_CONTR &= 0xE7; //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,return (ADC_RES); //返回 A/D 高 8 位转换结果}void delay(INT8U delay_time) // 延时函数{INT16U n;while(delay_time--){n = 100;while(--n);}}//---------------------------同道选择------------------------------------------void ADzhuanhuan1(INT8U zh){INT16U ADC_result;P1ASF = 0x02; //0000,0010, 将 P1.1 置成模拟口AUXR1 &= ~0x04; //0000,0100, 令 ADRJ=0 : 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器ADC_CONTR |= 0x80; //1000,0000 打开 A/D 转换电源while(1){ADC_result =get_AD_result(zh);//P1.1 为 A/D 当前通道,测量并发送结果led(ADC_result*19.53); //显示数值。

stc12c5a60s2使用片内AD转换

stc12c5a60s2使用片内AD转换

stc12c5a60s2使用片内AD转换#include#include#define uint unsigned int#define uchar unsigned charsfr adc_contr=0xbc;//adc 控制寄存器,不可位寻址,用或运算来设置sfradc_res=0xbd;//转换结果寄存器,高八位sfr adc_low2=0xbe;//转换结果寄存器,低两位sfr p1asf=0x9d;//设置p1 的那一口为输入口,不可位寻址.//以下都是控制寄存器的各位地址#define adc_power 0x80;//adc 电源,第7位#define adc_flag0x10;//转换结束标志位,第4位#define adc_start 0x08;//转换开始,第3位#define adc_speedll 0x00;//速度位,第5,6位#define adc_speedl 0x20;#define adc_speedh 0x40;#define adc_speedhh 0x60;#define adc_chs 0x00;//输入通道为第p1.0,1,2,3三位可设置p10-p17//位定义完成sbit duan=P2;sb it wei=P2;long unsigned int a,shu;uintb,wan,qian,bai,shi,ge,adc_finished;//转换结束标志uchar code Temp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void yanshi(){uchari,j;for(i=5;i>0;i--)for(j=110;j>0;j--);}void adcinit()//adc 初始化函数{p1asf=0x01;//设置p10 为ad 转换输入口adc_contr=0xe0;//打开电源,设最高速度//adc_contr=adc_power|adc_speedh|adc_chs;//电源X0000000,速度0XX00000//通道:00000XXXyanshi();adc_contr|=adc_chs;//设置频道}void fenshu(){shu=a;wan=shu/10000;shu=shu%10000;qian=shu/1000;shu=shu%1000;bai=shu/100; shu=shu%100;shi=shu/10;ge=shu%10;}voidxianshi(){P0=Temp[ge];duan=1;duan=0;P0=0xff;P0=0x7f;wei=1;wei=0;P0=0x00; yanshi();P0=Temp[shi];duan=1;duan=0;P0=0xff;P0=0xbf;wei=1;wei=0;。

增强型51单片机STC12C5A60S2的内部AD和PWM波以及时钟输出程序

增强型51单片机STC12C5A60S2的内部AD和PWM波以及时钟输出程序

增强型51单片机STC12C5A60S2的内部AD和PWM波以及时钟输出程序#ifndef __ad_h__#define __ad_h__uint adzhi[8]; //AD值存放数组void AD_Init(){AUXR1|=0X04; //设置AD的ADRJ位为1,使AD取十位结果RES寄存器存高两位,RESL存低七位ADC_CONTR=0X80; //开AD转换电源,第一次使用时要打开内部模拟电源delayms(1);P1ASF=0xff; //P1口7路ADC}void Get_AD(){uchar i;uint res,resl; //AD结果暂存变量uchar status=0; //AD转换状态ADC_CONTR=0X80; //再次打开电源delayms(1);for(i=0;i<8;i++){ADC_CONTR=(0X80|i); //设定转换的通道ADC_CONTR|=0x08; //开始AD转换status=0;while(!(ADC_CONTR&0x10));//等待转换完成ADC_CONTR&=0xE7; //清零即D3位start清零,D4位转换结束标志位ADC——flag清零res=ADC_RES; //存储高两位resl=ADC_RESL; //存储低八位adzhi[i]=res*256+resl;}}void PWM_Init(){CMOD=0X84; //初始化工作模式寄存器CCON=0X00; //所有标志位清零CL=0;CH=0; //给PCA的16位计数器赋初值CCAP0H=CCAP0L=0x80; //给占空比100%CCAPM0=0X42; //工作在PWM波模式,且无PCA中断PCA_PWM0=0X00; //最高位给00CCAP1H=CCAP1L=0x80; //给PWM1占空比50%CCAPM1=0X42; //工作模式设定PCA_PWM1=0x00;CR=1; //启动}void CLK(){TMOD=0X22; //T0、T1工作在方式2,8位自动重装AUXR|=0X80; //T0工作在1T模式AUXR|=0X40; //T1工作在1TAUXR|=0X04; //独立波特率发生器工作在1TBRT=106;TH0=106;TH1=106;WAKE_CLKO|=0X07; //允许T0、T1,独立波特率发生器输出时钟TR0=1; //启动计数TR1=1;AUXR|=0X10; //启动BRT工作,对系统时钟进行分频输出while(1);}#endif。

stc12c5a60s2AD

stc12c5a60s2AD

1. P1口模拟功能控制寄存器P1ASF与STC12C5A60S2系列单片机A/D转换相关的寄存器列于下表所示STC12C5A60S2系列单片机的A/D转换通道与P1口(P1.7-P1.0)复用,上电复位后P1口为弱上拉型I/O口,用户可以通过软件设置将8路中的任何一路设置为A/D转换,不需作为A/D使用的P1口可继续作为I/O口使用(建议只作为输入)。

需作为A/D 使用的口需先将P1ASF特殊功能寄存(建议只作为输入)。

需作为A/D使用的口需先将P1ASF特殊功能寄存器中的相应位置为‘1’,将相应的口设置为模拟功能。

P1ASF寄存器的格式如下:P1ASF : P1口模拟功能控制寄存器(该寄存器是只写寄存器,读无效)当P1口中的相应位作为A/D使用时,要将P1ASF中的相应位置1.2. ADC控制寄存器ADC_CONTRADC_CONTR寄存器的格式如下:ADC_CONTR : ADC控制寄存器对ADC_CONTR寄存器进行�作,建议直接用MOV赋�语句,不要用‘与’和‘或’语句。

ADC_POWER: ADC电源控制位。

0:关闭A/D转换器电源;1:打开A/D转换器电源.建议进入空闲模式前,将ADC电源关闭,即ADC_POWER =0。

启动A/D转换前一定要确认A/D电源已打开,A/D转换结束后关闭A/D电源可降低功耗,也可不关闭。

初�打开内部A/D转换模拟电源,需适当延时,等内部模拟电源稳定后,再启动A/D转换。

建议启动A/D转换后,在A/D转换结束之前,不改变任何I/O口的状态,有利于高精度A/D转换,若能将定时器/串行口/中断系统关闭更好。

SPEED1,SPEED0:模数转换器转换速度控制位ADC_FLAG: 模数转换器转换结束标志位,当A/D转换完成后,ADC_FLAG=1,要由软件清0。

,当A/D转换完成后,ADC_FLAG=1,要由软件清0。

不管是A/D转换完成后由该位申请产生中断,还是由软件查询该标志位A/D转换是否结束,当A/D转换完成后,ADC_FLAG = 1,一定要软件清0。

STC12C5A60S2单片机的10位AD转换程序

STC12C5A60S2单片机的10位AD转换程序

STC12C5A60S2单片机的10位AD转换程序#include"stc12c5a.h" //头文件在STC公司主页上下载#include"stdio.h" //输入输出函数#include"intrins.h"//------------------------------------------------------------------------------void AD_init(); //初始化ADvoid serial_init();void delay(unsigned int a);float AD_work(unsigned char channel);unsigned int AD_get(unsigned char channel);//------------------------------------------------------------------------------void main() //主程序{AD_init(); //A/D转换初始化serial_init(); //串口初始化while(1){unsigned char i;for(i=0;i<8;i++) //循环发送P1.0-P1.7的转换数值{TI=1; //使用printf函数前须先将发送标志位TI置1printf("The P1.%bd voltage is %f\n",i,AD_work(i));TI=0;delay(1000); //延时约1s}}}//------------------------------------------------------------------------------unsigned int AD_get(unsigned char channel){ADC_CONTR=0x88|channel; //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0_nop_(); _nop_(); _nop_(); _nop_(); //要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器while(!(ADC_CONTR&0x10)); //等待转换完成ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)}//------------------------------------------------------------------------------float AD_work(unsigned char channel){float AD_val; //定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i<100;i++)AD_val+=AD_get(channel); //转换100次求平均值(提高精度)AD_val/=100;AD_val=(AD_val*5)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;}//------------------------------------------------------------------------------void delay(unsigned int a) //延时约1ms{unsigned int i;while (--a!=0)for(i=600;i>0;i--); //1T单片机i=600,若是12T单片机i=125}//------------------------------------------------------------------------------void serial_init(){TMOD=0x20;TH1=0xfd;TL1=0xfd; //设置9600波特率SCON=0x50; //串口方式1,允许接收TR1=1;}//------------------------------------------------------------------------------void AD_init(){P1ASF=0xff; //P1口全部作为模拟功能AD使用ADC_RES=0; //清零转换结果寄存器高8位ADC_RESL=0; //清零转换结果寄存器低2位ADC_CONTR=0x80;//开启AD电源delay(2); //等待1ms,让AD电源稳定}/*。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

系统说明:本人想用STC12C5A60S2自带的A/D对电源电压进行检测(暂定3.3V),晶振:12M,电压从P1.0口输入,检测后的电压值在1602上进行显示,附上硬件大致原理图,硬件部分是照STC12C5A60S2芯片资料上设计,大家看看有错没?硬件原理简图(原文件名:clip_image001.gif)程序的A/D部分也是从官网资料上搬下来的,只自己稍微改了一下对读取到的A/D转换结果的数据处理,液晶部分是前阵子写的搬过来的。

大家帮我看看哪出问题了?程序如下:#include<reg51.h>#include "intrins.h"#define uchar unsigned char#define uint unsigned intuchar Vo; //A/D转换后换算的电压值/*Declare SFR associated with the ADC */sfr ADC_CONTR = 0xBC; //ADC control registersfr ADC_RES = 0xBD; //ADC high 8-bit result registersfr ADC_RESL = 0xBE;//sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result registersfr P1ASF = 0x9D; //P1 secondary function control register/*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 模数转换启动控制位//转换速度控制位SPEED0和SPEED1,共四种状态,对应四种转换速度#define ADC_SPEEDLL 0x00 //540 clocks#define ADC_SPEEDL 0x20 //360 clocks#define ADC_SPEEDH 0x40 //180 clocks#define ADC_SPEEDHH 0x60 //90 clocksuchar tCount;sbit RS = P0^4;sbit RW = P0^5;sbit EN = P0^6;void DelayMS(uint ms){uint i;while(ms--){for(i=0;i<120;i++);}}/*----------------------------Software delay function----------------------------*/void Delay(uint n){uint x;while (n--){x = 5000;while (x--);}}/*----------------------------Initial ADC sfr----------------------------*/void InitADC(){P1ASF = 0x01; //选择P1.0作为A/D输入通道ADC_RES = 0; //清0ADC_CONTR = ADC_POWER | ADC_SPEEDLL; //0x10|0x00=0x10:开电源和设置A/D转换速度Delay(2); //ADC power-on and delay}/*----------------------------Get ADC result----------------------------*/uchar GetADCResult(uchar ch){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 flagADC_CONTR &= ~ADC_FLAG; //Close ADCVo=ADC_RES*5*10/256; //Return ADC result(为显示整数,这里将电压值扩大了十倍)return Vo;}uchar Read_LCD_State(){uchar state;RS=0;RW=1;EN=1;DelayMS(1);state=P2;EN = 0;DelayMS(1);return state;}void LCD_Busy_Wait(){while((Read_LCD_State()&0x80)==0x80);DelayMS(5);}void Write_LCD_Data(uchar dat) //写数据到1602{LCD_Busy_Wait();RS=1;RW=0;EN=0;P2=dat;EN=1;DelayMS(1);EN=0;}void Write_LCD_Command(uchar cmd) //写命令{LCD_Busy_Wait();RS=0;RW=0;EN=0;P2=cmd;EN=1;DelayMS(1);EN=0;}void Init_LCD() //1602 初始化{Write_LCD_Command(0x38);DelayMS(1);Write_LCD_Command(0x01); //清屏DelayMS(1);Write_LCD_Command(0x06); //DelayMS(1);Write_LCD_Command(0x0c);DelayMS(1);}void Set_LCD_POS(uchar p){Write_LCD_Command(p|0x80);}void Display_LCD_String(uchar p,uchar *s) //1602显示{uchar i;Set_LCD_POS(p);for(i=0;i<16;i++){Write_LCD_Data(s);DelayMS(1);}}void Format_DateTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}//写入液晶第二行void display(uchar add,uchar date){uchar shi,ge;shi=date/10+'0';ge=date%10+'0';Write_LCD_Command(0x80+0x40+add);Write_LCD_Data(shi);Write_LCD_Data(ge);}//写入液晶第一行void display1(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;Write_LCD_Command(0x80+add);Write_LCD_Data(0x30+shi); //0x30即48(十进制)对应的ASCAII码为字符‘0’ Write_LCD_Data(0x30+ge);}void main(){Init_LCD();InitADC();while (1){GetADCResult(0);Display_LCD_String(0,"dianya:");display1(7,Vo);Display_LCD_String(9,"V ");DelayMS(1000);}}程序二:* 文件名:AD_CAIYANG.C* 功能:使用AD采集电压显示在LCD* 说明:转自网络,本人验证通过****************************************************************************/ #include<STC12C5A60S2.H>#define uint unsigned int#define uchar unsigned charsbit CS=P2^0; //LCD12864串行通信片选sbit SID=P2^1; //LCD12864串行通信数据口sbit SCLK=P2^2; //LCD12864串行通信同步时钟信号sbit PSB=P2^5; //LCD12864并/串选择:H并行 L串行unsigned int temp1,sh1,ge1,n1,m1;unsigned char ad_result_data[10]; //AD转换高八位unsigned char ad_result_low2[10]; //AD转换低八位unsigned char ad_result_total[10]; //AD转换总十位unsigned char ad_average_result; //AD转换十次的平均值unsigned char Ain,Vin;unsigned char b,t,R;char tp=0;unsigned char code ma1[6]={0xb5,0xe7,0xd1,0xb9,0xa1,0xc3}; //电压:unsigned char code ma2[]={"."};uchar code disp1[]={"提示: 按1 键进入"};uchar code disp2[]={"功能选择界面. "};unsigned char code num0[]={0xa3,0xb0};unsigned char code num1[]={0xa3,0xb1};unsigned char code num2[]={0xa3,0xb2};unsigned char code num3[]={0xa3,0xb3};unsigned char code num4[]={0xa3,0xb4};unsigned char code num5[]={0xa3,0xb5};unsigned char code num6[]={0xa3,0xb6};unsigned char code num7[]={0xa3,0xb7};unsigned char code num8[]={0xa3,0xb8};unsigned char code num9[]={0xa3,0xb9};//-------模块延时程序---------------------------- 1msvoid delay1ms(uint delay1ms) //STC11F60XE,22.1184M,延时1ms{uint i,j;for(;delay1ms>0;delay1ms--)for(i=0;i<7;i++)for(j=0;j<210;j++);}void delay(uint delay) //STC11F60XE,22.1184M,延时170us{uint i,j;for(;delay>0;delay--)for(i=0;i<124;i++);for(j=0;j<124;j++);}/*******************************************************AD转换程序*******************************************************/void AD_initiate() //初始化函数{ES=0;TMOD=0x21; //定时计数器方式控制寄存器,"自动重装,16位计数器".SCON=0x50; //串行控制寄存器,方便在串口助手那观察TH1=0xfa;TL1=0xfa;TR1=1;}void ADC_Power_On() //AD转换电{ADC_CONTR|=0x80;delay(5); //必要的延时}void get_ad_result() //取AD结果函数,它是十位AD转换,每十次平均,最后取低八位作为AD采样数据{uint i,q=0;for(i=0;i<10;i++){tp=0;ADC_RES=0; //高八位数据清零,STC12C5A60S2 AD数据寄存名与STC12C54××系列不同ADC_RESL=0; //低两位清零ADC_CONTR|=0x08; //启动AD转换while(!tp) //判断AD转换是否完成{tp=0x10;tp&=ADC_CONTR;}ADC_CONTR&=0xe7;ad_average_result=ADC_RES;q=q+ad_average_result;}ad_average_result=q/10;//ad_average_result=ad_average_result*4*5000/1024;}/************************AD转换结束***********************/void send_ad_result() //取AD结果函数发送到串口,方便调试{SBUF=n1;while(TI==0) ;TI=0;delay1ms(100);//SBUF=R>>4;}//---------------------电压采样程序-------------------------void caiyangP10() //测电压{P1M0|=0x01; //设P1_0为开漏模式如: P1_0= #00000000BP1M1|=0x01;ADC_CONTR=0xe0; //设置P1.0为输入AD转换口delay(2);get_ad_result(); //取转换数据Vin=ad_average_result;R=Vin;}/*-----------写控制字到LCD12864------------*/void write_cmd(uchar cmd){uchar i;uchar i_data;i_data=0xf8; //命令控制字:11111000写指令 11111010写数据 11111100读状态 11111110读数据CS=1; //片选置高,才能进行读写操作SCLK=0;/*----------写命令控制字-----------------*/for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*---------------------------------------*//*----------写指令高四位-----------------*/i_data=cmd;i_data=i_data&0xf0; //把低四位置0for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*---------------------------------------*//*----------写指令低四位-----------------*/i_data=cmd;i_data=i_data<<4; //左移四位,把低四位的数据移到高四位,再把低四位置0 for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*-----------------------------------------*/CS=0; //把片选置低delay1ms(5); //延时是因为没有进行忙检测,适当的延时可以不进行忙检测}/*-----------------------------------------*//*------------写数据到LCD12864-------------*/void write_dat(uchar dat){uchar i;uchar i_data;i_data=0xfa;CS=1;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}i_data=dat;i_data=i_data&0xf0;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}i_data=dat;i_data=i_data<<4;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}CS=0;delay1ms(5);}/*-----------------------------------------*//*--------------显示坐标-------------------*/void lcd_pos(uchar x,uchar y) //汉字显示坐标,x为哪一行,y为哪一列{uchar pos;if(x==0)x=0x80; //第一行else if(x==1)x=0x90; //第二行else if(x==2)x=0x88; //第三行else if(x==3)x=0x98; //第四行pos=x+y; //显示哪一行(总共有4行)哪一竖(总共有8竖,每16列为1竖)write_cmd(pos);}/*-----------------------------------------*//*--------------显示8个汉字-------------------*/void disp_hanzi(uchar code *chn){uchar i;write_cmd(0x30); //基本指令操作方式for(i=0;i<16;i++) //16列*8个汉字=128(刚好)write_dat(chn[i]);}/*-----------------------------------------*//*--------------显示数字-------------------*/void disp_num(uchar code *chn){uchar i;write_cmd(0x30); //基本指令操作方式for(i=0;i<2;i++) //1个数字write_dat(chn[i]);}void disp_number(uchar num){switch(num){case 0: disp_num(num0);break;case 1: disp_num(num1);break;case 2: disp_num(num2);break;case 3: disp_num(num3);break;case 4: disp_num(num4);break;case 5: disp_num(num5);break;case 6: disp_num(num6);break;case 7: disp_num(num7);break;case 8: disp_num(num8);break;case 9: disp_num(num9);break;default: break;}}/*----------- --LCD初始化------------------*/void lcd_init(){PSB=0;write_cmd(0x30); //基本指令write_cmd(0x02); //地址归位write_cmd(0x06); //游标右移write_cmd(0x0c); //整体显示write_cmd(0x01); //清屏}/*-----------------------------------------*/void displayP10(){float ad1;//unsigned int temp1,sh1,ge1,n1,m1;//uchar code dis2[]={0x01,0x02,0x00};//ad1=x*7.8125; //电压修正uchar i;ad1=Vin*3.9608; //具体线性参数由输入电压值调整,该值的测量范围为0-10.00V,5V 左右的测量比较准确,//两端的最大误差为70mv,其他一般在40mv以内temp1=(int)ad1;sh1=temp1/1000; //十位ge1=(temp1%1000)/100; //个位n1=((temp1%1000)%100)/10; //小数点后一位m1=((temp1%1000)%100)%10; //小数点后二位//write_cmd(0x01);write_cmd(0x30); //基本指令操作方式lcd_pos(0,0);for(i=0;i<6;i++) write_dat(ma1[i]);lcd_pos(0,3);disp_number(sh1);lcd_pos(0,4);disp_number(ge1);lcd_pos(0,5);for(i=0;i<2;i++) write_dat(ma2[i]);lcd_pos(0,6);disp_number(n1);lcd_pos(0,7);disp_number(m1);/*lcd_pos(2,0);disp_hanzi(disp1);lcd_pos(3,0);disp_hanzi(disp2);*/}void main(){EA=1;AD_initiate(); //初始化ADC_Power_On(); //开AD电源//init();lcd_init();delay(10);while(1){caiyangP10(); //测电压 send_ad_result();//Vin=Vin*4007;displayP10();delay(10);}}。

相关文档
最新文档