STC12C5A60S2自带10位AD测量电压值LCD1602显示(C程序)
STC12C5A60S2 1602驱动程序
功 能: 初始化MCU串口(带1位奇校验)
参 数: 无
返回值 : 无
********************************************************************/
void UART1_INIT(void)
函数名称: IRQ_INIT
功 能: 中断初始化
参 数: 无
返回值 : 无
********************************************************************/
void IRQ_INIT(void)
{
// EX0 = 1; //开外部中断0
函数名称: Delay_nop
功 能: 延迟指定CPU cycle
参 数: dwTime - 延迟的CPU周期数
返回值 : 无
********************************************************************/
void Delay_nop (unsigned int dwTime)
ES = 1; //开UART1中断
IE2 |= 0x01; //开UART2中断
// IE2 |= 0x02; //开SPI中断
EADC = 1; //开ADC中断
EA = 1; //开总中断
}
/********************************************************************
#define NONE_PARITY 0 //无校验位
基于STC12C5A60S2单片机测电压的c代码
//------------------------------------------------------------------------------
void display(void)
{ char i,scan;
char times=20;
whlie(--time>=0)
serial_init(); //串口初始化
while(1)
{
unsigned char i;
for(i=0;i<8;i++) //循环发送P1.0-P1.7的转换数值
{
TI=1; //使用printf函数前须先将发送标志位TI置1
printf("The P1.%bd voltage is %f\n",i,AD_work(i));
void dataproc(unsigned char);
void display();
void delay1ms(char);
void AD_init();
void serial_init();
void delay(unsigned int a);
float AD_work(unsigned char channel);
#include"stc12c5a.h" //头文件在STC公司主页上下载
#include"stdio.h"
#include"intrins.h"
#include<reg51.h>
char code TAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xf8,0x80,0x98};
STC12C5A60S2单片机c语言程序代码调试例程
//12T指的是每12个时钟加1与普通C51一样
//允许将P3.5/T1脚配置为定时器1的时钟输出CLKOUT1,只
能工作在定时器模式2下
//T1工作在1T模式时的输出频率 = SYSclk/(256-TH0)/2
//T1工作在12T模式时的输出频率 = SYSclk/12/(256-TH0)/2
//工作模式为1T
BRT = 0xff;
#if( Bus_clk == 12 )
CLK_DIV = 0x00;
#elif( Bus_clk == 6 )
CLK_DIV = 0x01;
#elif( Bus_clk == 3 )
CLK_DIV = 0x02;
#elif( Bus_clk == 1500 )
void Delay_ms( uint time )
{
uint t; //延时时间 = (time*1003+16)us while(time--)
{
for( t = 0; t < 82; t++ );
}
}
//***********************************//
//1T指的是每1个时钟加1,是普通C51的12倍
//12T指的是每12个时钟加1与普通C51一样
AUXR = 0xc0; //T0定时器速度是普通8051的12倍,即工作在1T模式下
//T1定时器速度是普通8051的12倍,即工作在1T模式下
TMOD = 0x22; //定时器0工作模式为方式2,自动装载时间常数
#define uchar unsigned char
stc12c5a60s2 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转换功能。
于是写了这段程序测试学习一下,程序在我的学习板上运行稳定,如里要你只要改下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串行显示终极程序带滤波作者:电子工程师(天津)由于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的1602液晶屏显示【
#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit lcdrs=P2^7;sbit lcden=P2^6;uchar code stringtable[4]={'a','b','c','d'};void delay(uint z) //1ms延时子程序{uint x,y;for(x=z;x>0;x--){for(y=240;y>0;y--);}}void write_com(com) //1602lcd写命令子程序{lcdrs=0;delay(2);//为开启写入命令的时间>后面程序执行时间和延长时间之和才行。
P0=com;lcden=1;delay(2);lcden=0;}void write_data(date) //1602lcd写数据子程序{lcdrs=1;delay(2);P0=date;lcden=1;delay(2);lcden=0;}void lcd_init(){delay(15);//读取子程序所用大约时间write_com(0x38);write_com(0x0e);write_com(0x06);}void main() //先让内容显示出来,在让它整体移动。
{uchar number,k;lcd_init();//主程序中须先声明屏幕的显示设置就像未知数须先定义一样。
while(1){write_com(0x80+0x09);//要先写明显示的初始地址,才能写入数据。
上行显示for(number=0;number<4;number++){write_data(stringtable[number]);}delay(3000);write_com(0x01); //清屏delay(10);write_com(0x80+0x40+0x09);//要先写明显示的初始地址,才能写入数据。
STC12C5A60S2单片机实现AD采样并液晶显示
rw=0; lcden=0; delay(10); lcden=1; delay(10); lcden=0; } void LCD_init() //液晶显示初始化 { write_com(0x38); _nop_(); write_com(0x0f); _nop_(); write_com(0x06); _nop_(); write_com(0x01); _nop_(); } void channel1() //采集通道1函数 { uchar num1; AD_init1(); for(i=20;i>0;i--) { AD_sample(); ver1+=AD_sample(); } ver1=ver1/22; write_com(0X80); display(ver1); if(ver1>3) num1--; else if(ver1<3) num1++; if(num1==1||num1==7) num1=4; } void channel2() //采集通道2函数 { uchar num2; AD_init2(); for(j=20;j>0;j--) { AD_sample();
uint a,b; for(a=x;a>0;a--) for(b=200;b>0;b--); } void AD_init1() //通道1初始化 { P1M0|=0x10; P1M1|=0x10; P1ASF=0x10; ADC_RES=0; ADC_RESL=0; ADC_CONTR=0xEC; _nop_(); _nop_(); _nop_(); _nop_(); }
TH1=(65536-5)/256; TL1=(6-5)%256; a++; pwm(); } 头文件 stc12c5a60s2.h 可以到官网下载。
STC12C5A60S2单片机实现音频信号的频谱显示(在LCD上显示)
利用STC12C5A60S2单片机实现音频信号的频谱显示(在LCD上显示)思路:外来音频信号经过51单片机,在单片机中进行频谱分析,并将结果显示在LCD(12864或1602)上要求:频谱显示如同千千静听播放音乐时的频谱显示希望各位高手能给出详细的解决方案,感激。
51做FFT有些困难,可以使用增强型(RAM)的51机子进行参考程序:#include<STC12C5A.H>#define uchar unsigned char#define uint unsigned int#define channel 0x01 //设置AD通道为 P1.1//---------------------------------------------------------------------sbit SDA_R=P1^2;sbit SDA_R_TOP=P1^3;sbit SDA_G=P1^4;sbit SDA_G_TOP=P1^5;sbit STCP=P1^6;sbit SHCP=P1^7;//---------------------------------------------------------------------//----------------------------------------------------------------------------------------------------------------------//放大128倍后的sin整数表(128)code char SIN_TAB[128] = { 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70, 75, 80, 85, 89, 94, 98, 102,105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126, 126, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112,108, 105, 102, 98, 94, 89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30,-36, -42, -48, -54, -59, -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121,-123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102,-98, -94, -89, -85, -80, -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6 };//放大128倍后的cos整数表(128)code char COS_TAB[128] = { 127, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112, 108, 105, 102, 98, 94,89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30, -36, -42, -48, -54, -59,-65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121, -123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102, -98, -94, -89, -85, -80,-75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70,75, 80, 85, 89, 94, 98, 102, 105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126 };//采样存储序列表code char LIST_TAB[128] = { 0, 64, 32, 96, 16, 80, 48, 112,8, 72, 40, 104, 24, 88, 56, 120,4, 68, 36, 100, 20, 84, 52, 116,12, 76, 44, 108, 28, 92, 60, 124,2, 66, 34, 98, 18, 82, 50, 114,10, 74, 42, 106, 26, 90, 58, 122,6, 70, 38, 102, 22, 86, 54, 118,14, 78, 46, 110, 30, 94, 62, 126,1, 65, 33, 97, 17, 81, 49, 113,9, 73, 41, 105, 25, 89, 57, 121,5, 69, 37, 101, 21, 85, 53, 117,13, 77, 45, 109, 29, 93, 61, 125,3, 67, 35, 99, 19, 83, 51, 115,11, 75, 43, 107, 27, 91, 59, 123,7, 71, 39, 103, 23, 87, 55, 119,15, 79, 47, 111, 31, 95, 63, 127};uchar COUNT=0,COUNT1=0,ADC_Count=0,LINE=15,G,T;uchar i,j,k,b,p;int Temp_Real,Temp_Imag,temp; // 中间临时变量uint TEMP1;int xdata Fft_Real[128];int xdata Fft_Image[128]; // fft的虚部uchar xdata LED_TAB2[64]; //记录漂浮物是否需要停顿一下uchar xdata LED_TAB[64]; //记录红色柱状uchar xdata LED_TAB1[64]; //记录漂浮点void Delay(uint a){while(a--);}void FFT(){ //uchar X;for( i=1; i<=7; i++) /* for(1) */{b=1;b <<=(i-1); //碟式运算,用于计算隔多少行计算例如第一极 1和2行计算,,第二级for( j=0; j<=b-1; j++) /* for (2) */{p=1;p <<= (7-i);p = p*j;for( k=j; k<128; k=k+2*b) /* for (3) 基二fft */{Temp_Real = Fft_Real[k]; Temp_Imag = Fft_Image[k]; temp = Fft_Real[k+b];Fft_Real[k] = Fft_Real[k] +((Fft_Real[k+b]*COS_TAB[p])>>7) + ((Fft_Image[k+b]*SIN_TAB[p])>>7); Fft_Image[k] = Fft_Image[k] -((Fft_Real[k+b]*SIN_TAB[p])>>7) + ((Fft_Image[k+b]*COS_TAB[p])>>7); Fft_Real[k+b] = Temp_Real -((Fft_Real[k+b]*COS_TAB[p])>>7) - ((Fft_Image[k+b]*SIN_TAB[p])>>7); Fft_Image[k+b] = Temp_Imag + ((temp*SIN_TAB[p])>>7) -((Fft_Image[k+b]*COS_TAB[p])>>7);// 移位.防止溢出. 结果已经是本值的 1/64 Fft_Real[k] >>= 1;Fft_Image[k] >>= 1;Fft_Real[k+b] >>= 1;Fft_Image[k+b] >>= 1;}}}// X=((((Fft_Real[1]*Fft_Real[1]))+((Fft_Image[1]*Fft_Image[1])))>>7);Fft_Real[0]=Fft_Image[0]=0; //去掉直流分量// Fft_Real[63]=Fft_Image[63]=0;for(j=0;j<64;j++){TEMP1=((((Fft_Real[j]*Fft_Real[j]))+((Fft_Image[j]*Fft_Image[j])))>>1);//求功率if(TEMP1>1)TEMP1--;else TEMP1=0;if(TEMP1>31)TEMP1=31;if(TEMP1>(LED_TAB[j]))LED_TAB[j]=TEMP1;if(TEMP1>(LED_TAB1[j])){ LED_TAB1[j]=TEMP1;LED_TAB2[j]=18; //提顿速度=12}}}void Init(){//-----------------------------------------------------------------------------------P1ASF = 0x02; //0000,0010, 将 P1.1 置成模拟口AUXR1 &=0xFB; //1111,1011, 令 ADRJ=0EADC=1; //AD中断打开ADC_CONTR = ADC_POWER | ADC_SPEEDHH | ADC_START | channel;//1110 1001 1打开 A/D (ADC_POWER)转换电源;11速度为70周期一次;//0中断标志清零;1启动adc(ADC_START);001AD通道打开(这里为P1.1);//-----------------------------------------------------------------------------------P2M0=1;P0M0=1;TMOD=0X12;TH0=0x30; //大约20K的采样率(要完整频段需40K以上。
最新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电源稳定}/* 酱炒牛柳条:Sautéed Beef Filet in XO Sauce阿香婆石头烤肉:Beef BBQ with Spicy Sauce八宝菠菜:Spinach with Eight Delicacies白菜豆腐焖酥肉:Braised Pork Cubes with Tofu and Chinese Cabbage白菜心拌蜇头:Marinated Jellyfish and Chinese Cabbage in Vinaigrette白灵菇扣鸭掌:Mushrooms with Duck Feet白灵菇牛柳:Stir-Fried Beef Filet with Mushrooms白切鸡:Boiled Chicken with Sauce白灼肥牛:Scalded Beef百叶结烧肉:Stewed Pork Cubes and Tofu Skin in Brown Sauce 板栗红烧肉:Braised Pork with Chestnuts拌八爪鱼:Spicy Cuttlefish拌豆腐丝:Shredded Tofu with Sauce拌海螺:Whelks and Cucumber拌苦菜:Mixed Bitter Vegetables拌茄泥:Mashed Eggplant with Garlic拌双耳:Tossed Black and White Fungus拌爽口海苔:Sea Moss with Sauce拌香椿苗:Chinese Toon with Sauce包子:Baozi鲍鱼红烧肉:Braised Pork with Abalone鲍汁扣东坡肉:Braised Dongpo Pork with Abalone Sauce。
STC12C5A60S2AD功能的使用
STC12C5A60S2系列单片机AD功能详解作者:裴博宇作者原本旨在对STC12C5A60S2(后文简称该单片机、12C单片机)系列单片机相对传统51内核单片机升级内容进行详细解析,和程序应用分析,但是由于时间原因只写到了AD 的查询方式使用,抱歉了,如果有什么错误欢迎批评指正,但是申明本人是一个学生,文章也只适合于初学者,希望行业的老人不要骂的太狠。
本文以STC12C5A60S2系列单片机芯片手册为母本编写。
一、相关寄存器介绍12C单片机自带8路10位AD,要使用他就必须明确其相关寄存器:P1AS F寄存器P1口模拟配置寄存器,地址:9DH,复位值:00H。
12C单片机的AD转换引脚与P1I/O口复用,P1ASF寄存器指定P1寄存器哪一位用于AD转换,哪一位做I/O口用。
具体是,P1ASF寄存器的8位对应P1的8位,1代表做AD 转换通道用,0代表做I/O口用。
不可位寻址。
ADC_CONTR 寄存器ADC控制寄存器,地址BCH,复位值:00H。
位说明:ADC_CONTR.7(这种写法其实是有问题的,因为该寄存器不支持位寻址,仅供阅读方便)——ADC_POWER。
ADC开关,要使用AD转换功能该位必须置“1”。
开在初始化时直接将其置“1”,但考虑到能耗的因素,最好在使用时开启,使用结束后关闭。
ADC_CONTR.6——SPEED1、ADC_CONTR.5——SPEED2,AD转换速率控制寄存器。
00——540个时钟周期转换一次;01——360个时钟周期转换一次;10——180个时钟周期转换一次;11——90个时钟周期转换一次。
转换速率并非越快越好,当然从效率角度来讲我们希望他更快,但是转换速率愉快能耗越高,同时准确度越低,所以请选择一个合理的周期。
ADC_CONTR.5——FLAG,AD转换结束标志位。
当AD转换结束时,自动拉高,标志转换结束。
注意,需用软件拉低。
ADC_CONTR.4——SRART,AD转换启动位。
STC12C5A60S2两路AD采集用LCD1602显示
STC12C5A60S2两路AD采集用LCD1602显示#include#include#include "stdio.h"#define ulong unsigned long#define uint unsigned int#define uchar unsigned charuchar data adc _at_ 0x30;uchar data adc1 _at_ 0x31;sbit E=P2^7; //1602使能引脚sbit RW=P2^6; //1602读写引脚sbit RS=P2^5; //1602数据/命令选择引脚void SendByte(unsigned char dat);void SendStr(unsigned char *s);void L1602_string(uchar hang,uchar lie,uchar *p);void L1602_char(uchar hang,uchar lie,char sign);uchar AD();uchar AD1();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);}}void delay(){_nop_();_nop_();}void Delay(uint del){uint i,j;for(i=0;i<del;i++)< p="">for(j=0;j<=148;j++){}}/************************************************************** ******* 名称: bit Busy(void)* 功能: 这个是一个读状态函数,读出函数是否处在忙状态* 输入: 输入的命令值* 输出: 无*************************************************************** ********/ void Busy(void){bit busy_flag = 1;P0 = 0xff;RS = 0;delay();RW = 1;delay();E = 1;//Delay(1);while(1){busy_flag = (bit)(P0 & 0x80);if(busy_flag == 0){break;}}E = 0;}/************************************************************** ******* 名称: wcmd(uchar del)* 功能: 1602命令函数* 输入: 输入的命令值* 输出: 无*************************************************************** ********/ void wcmd(uchar del){RS = 0;delay();RW = 0;delay();E = 0;delay();P0 = del;delay();E = 1;delay();E = 0;}/************************************************************** ******* 名称: wdata(uchar del)* 功能: 1602写数据函数* 输入: 需要写入1602的数据* 输出: 无*************************************************************** ********/void wdata(uchar del){delay();RS = 1;delay();RW = 0;delay();E = 0;delay();P0 = del;delay();E = 1;delay();E = 0;}/************************************************************** ******* 名称: L1602_init()* 功能: 1602初始化,请参考1602的资料* 输入: 无* 输出: 无*************************************************************** ********/ void L1602_init(void){Delay(15);wcmd(0x38);Delay(5);wcmd(0x38);Delay(5);wcmd(0x38);wcmd(0x38);Busy();wcmd(0x08);Busy();wcmd(0x01);Busy();wcmd(0x06);Busy();wcmd(0x0c);}/************************************************************** ******* 名称: L1602_char(uchar hang,uchar lie,char sign)* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下L1602_char(1,5,'b')* 输入: 行,列,需要输入1602的数据* 输出: 无*************************************************************** ********/void L1602_char(uchar hang,uchar lie,char sign){uchar a;if(hang == 1){a = 0x80;}if(hang == 2){a = 0xc0;}a = a + lie - 1;Busy();wcmd(a);Busy();wdata(sign);}/************************************************************** ******* 名称: L1602_string(uchar hang,uchar lie,uchar *p)* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下L1602_string(1,5,"ab cd ef;")* 输入: 行,列,需要输入1602的数据* 输出: 无*************************************************************** ********/ void L1602_string(uchar hang,uchar lie,uchar *p) {uchar a;if(hang == 1){a = 0x80;}if(hang == 2){a = 0xc0;}a = a + lie - 1;while(1){Busy();wcmd(a);Busy();wdata(*p);a++;p++;if((*p == '\0')||(a==0x90)||(a==0xd0)){break;}}}uchar AD(){ulong i;uchar star;ADC_CONTR|=0x80;for(i=0;i<10000;i++);P1ASF=0x01;ADC_CONTR|=0XE1;for(i=0;i<10000;i++); while(1){ADC_CONTR|=0x08; star=0;while(star==0){star=ADC_CONTR&0x10; }ADC_CONTR&=0x00; adc=ADC_RES;//adc<<=2;//adc+=ADC_RESL; return adc;}}uchar AD1(){ulong i;uchar star;ADC_CONTR|=0x80;for(i=0;i<10000;i++);P1ASF=0;ADC_CONTR|=0XE0;for(i=0;i<10000;i++);while(1){ADC_CONTR|=0x08;star=0;while(star==0){star=ADC_CONTR&0x10; }ADC_CONTR&=0x00;adc1=ADC_RES;// adc1<<=2;// adc1+=ADC_RESL; return adc1;}}void main(){float i,j;unsigned char a[16]; unsigned char b[16];L1602_init();while(1){{i=AD()*5/256;sprintf(a," DA1=%4.2f v",i); L1602_string(2,0,a); DelayMs(1);j=AD1()*5/256;sprintf(b," DC2=%4.2f v",j);L1602_string(1,0,b); }}}</del;i++)<>。
亲自调过的基于STC12C5A60S2的LCD1602显示屏程序
#include"STC12C5A60S2.h"
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
P0=dictate; //将数据送人p0口,写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
E=0; //当E由高电平变成低电平时,液晶模块开始
}
/********
函数功能:指定字符显示的地址
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
E=0; //写指令时E为高脉冲,让E从0到1发生正跳变,所以应先置零
_nop_();
_nop_();
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. "}; //第一行显示框架unsigned char pos_char_table[]= {" D "}; //显示位置unsigned char Lcd_Dis2_table[]= {"Voltage: V"}; //第二行显示框架unsigned char num_char_table[]= {" 9A.CD V"}; //显示位置sbit lcd_rs_port=P2^7; //定义LCD 控制端口,根据硬件调整sbit lcd_rw_port=P2^6;sbit lcd_en_port=P2^4;#define lcd_data_port P0void lcd_delay(uchar ms);//LCD1602延时void lcd_busy_wait(); //LCD1602忙等待void lcd_command_write(uint command); //LCD1602命令字写入void lcd_system_reset(); //LCD1602初始化voidlcd_char_write(uint x_pos,y_pos,lcd_dat); //LCD1602字符写入voidlcd_bad_check(); //LCD1602坏点检查void Num_to_Disp(uchar i, uint Num); //显示数据处理void LcdDisp(uchar j,uint num); //液晶显示函数/*------------------------以下为ADC 相应寄存器初始化及端口定义-------------*//***** 定义与ADC 相关的特殊功能寄存器*****/sfr ADC_CONTR = 0xBC; //ADC 控制寄存器sfr ADC_RES = 0xBD; //ADC hight8-bit result register sfr ADC_RESL = 0xBE; //ADC low2-bit result registersfr P1ASF = 0x9D; //P1 口功能控制寄存器P1ASF/************定义相应操作位***************/#define ADC_POWER0x80//ADC 电源控制位,0:关闭,1:打开#define ADC_FLAG 0x10//ADC 结束标志位#define ADC_START0x08 //ADC 启动控制位#define ADC_SPEEDLL 0x00 //540clocks___________选择转换速度/*------------------------以下为相关函数声明------------------------------*/void InitADC();uuuu GetADCResult(uchar ch);vvvv Delay(uint n);void delay_1ms(uchar x);/*-------------------------------- 主函数--------------------------------*/ void main(){//ADC 初始化//延时程序uchar i;lcd_system_reset(); //LCD1602 初始化lcd_bad_check(); //LCD1602 坏点检查InitADC(); //初始化ADC 特殊功能寄存器while(1){i = 0;while(i < 7){LcdDisp(i, GetADCResult(i)); //液晶1602 显示输入电压值(P1.0 -P1.7)Delay(1000);i++;}}}/*-------------------------------- ADC 取值------------------------------*/uint GetADCResult(uchar ch){ADC_CONTR= ADC_POWER | ADC_SPEEDLL | ch | ADC_START;_nop_(); //Must wait before inquiry_nop_();_nop_();_nop_();while(!(ADC_CONTR & ADC_FLAG)); //Wait complete flagADC_CONTR&=ADC_FLAG;//Close ADCreturn (ADC_RES*4+ ADC_RESL); //Return ADC result}/*---------------------------- 初始化ADC 特殊功能寄存器-------------------*/void InitADC(){P1ASF=P1|0x3f;//Set P1.0 - P1.5 as analog input portADC_RES = 0; //Clear previous resultADC_RESL =0;ADC_CONTR= ADC_POWER | ADC_SPEEDLL ;Delay(20); //ADC power-on delay and Start A/D conversion}/*---------------------------- LCD1602相应函数---------------------------*////////////////以下为LCD 显示数据处理/////////////////void Num_to_Disp(uchar i, uint Num){float NUM;int xx,yy,zz;NUM=(Num*5/1024.0); //计算公式:10-bit A/D Conversion Result = 1024x(Vin/Vcc) xx = (int)NUM;yy= (int)((NUM-(float)(xx)) * 10);zz= (int)((NUM-(float)(xx)) * 100)%10;num_char_table[9] = data_char_table[xx/ 10]; //电压值十位num_char_table[10]=data_char_table[xx% 10]; //电压值个位num_char_table[12]=data_char_table[yy]; //电压值小数点后一位num_char_table[13]=data_char_table[zz]; //电压值小数点后两位?pos_char_table[13]=data_char_table[i]; //当前ADC接口}//////////////////以下为LCD 显示////////////////////void LcdDisp(uchar j,uint num){uint i=0;for (i=0;i<16;i++){lcd_char_write(i,0,Lcd_Dis1_table[i]);lcd_char_write(i,1,Lcd_Dis2_table[i]); //显示框架}Num_to_Disp(j,num);lcd_char_write(13,0,pos_char_table[13]);for(i =9;i<14;i++){lcd_char_write(i,1,num_char_table[i]); //显示电压}delay_1ms(100);}//////////////以下是LCD1602驱动程序////////////////void lcd_delay(uchar ms)/*LCD1602 延时*/{uchar j;while(ms--){for(j=0;j<250;j++){;}}}void lcd_busy_wait()/*LCD1602忙等待*/{lcd_rs_port=0;lcd_rw_port=1;lcd_en_port=1;lcd_data_port=0xff;while(lcd_data_port&0x80);lcd_en_port=0;}void lcd_command_write(uint command) /*LCD1602命令字写入*/ {lcd_busy_wait();lcd_rs_port=0;lcd_rw_port=0;lcd_en_port=0;lcd_data_port= command;lcd_en_port=1;lcd_en_port=0;}void lcd_system_reset()/*LCD1602 初始化*/{lcd_delay(20);lcd_command_write(0x38);lcd_delay(100);lcd_command_write(0x38);lcd_delay(50);lcd_command_write(0x38);lcd_delay(10);lcd_command_write(0x08);lcd_command_write(0x01);lcd_command_write(0x06);lcd_command_write(0x0c);}void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/ {x_pos &= 0x0f;/*X 位置范围0~15*/y_pos &= 0x01;/*Y 位置范围0~1*/if(y_pos==1)x_pos+=0x40;x_pos += 0x80;lcd_command_write(x_pos);lcd_busy_wait();lcd_rs_port=1;lcd_rw_port=0;lcd_en_port=0;lcd_data_port=lcd_dat;lcd_en_port=1;lcd_en_port=0;}void lcd_bad_check()/*LCD1602坏点检查*/{char i,j;for(i=0;i<2;i++){for(j=0;j<16;j++){lcd_char_write(j,i,0xff);}}lcd_delay(200);lcd_delay(200);lcd_delay(200);lcd_delay(100);lcd_delay(200);lcd_command_write(0x01);/* clear lcd disp */}//////////////////以上是LCD1602驱动程序/////////////////*-----------------------------void Delay(uint n){uint x;while(n--){}延时程序x = 500;while(x--);---------------------------*/}/*1MS 为单位的延时程序*/ void delay_1ms(uchar x){uchar j;while(x--){for(j=0;j<125;j++){;}}}。
基于STC12C5A60S2单片机数字电压表的设计说明
数字电压表的设计第1章引言在电量的测量中,电压、电流和频率是最基本的三个被测量,其中电压量的测量最为经常。
而且随着电子技术的发展,更是经常需要测量高精度的电压,所以数字电压表就成为一种必不可少的测量仪器。
数字电压表简称DVM,它是采用数字化测量技术,把连续的模拟量转换成不连续、离散的数字形式并加以显示的仪表。
由于数字式仪器具有读数准确方便、精度高、误差小、测量速度快等特而得到广泛应用。
传统的指针式刻度电压表功能单一,精度低,容易引起视差和视觉疲劳,因而不能满足数字化时代的需要。
采用单片机的数字电压表,将连续的模拟量如直流电压转换成不连续的离散的数字形式并加以显示,从而精度高、抗干扰能力强,可扩展性强、集成方便,还可与PC实时通信。
数字电压表是诸多数字化仪表的核心与基础。
以数字电压表为核心,可以扩展成各种通用数字仪表、专用数字仪表及各种非电量的数字化仪表。
目前,由各种单片机和A/D转换器构成的数字电压表作全面深入的了解是很有必要的。
目前,数字电压表的部核心部件是A/D转换器,转换的精度很大程度上影响着数字电压表的准确度,因而,以后数字电压表的发展就着眼在高精度和低成本这两个方面。
本文是以简易数字直流电压表的设计为研究容,本系统主要包括三大模块:转换模块、数据处理模块及显示模块。
第2章系统总体方案设计选择与说明2.1 设计要求1、增强型MCS-51系列单片机STC12C5A60S2为核心器件,组成一个简单的直流数字电压表。
2、采用1路模拟量输入,能够测量0-10V之间的直流电压值。
3、电压显示采用LCD1602显示。
4、尽量使用较少的元器件。
2.2 设计思路1、根据设计要求,选择STC12C5A60S2单片机为核心控制器件。
2、A/D转换采用STC12C5A60S2部自带A/D实现。
3、电压显示采用LCD1602显示。
2.3 设计方案硬件电路设计由7个部分组成:STC12C5A60S2单片机系统,数码管显示系统、时钟电路、复位电路档位调节电路以及测量电压输入电路。
STC12C5A60(32)S2单片机AD采样-LCD1602液晶显示程序
STC12C5A60(32)S2单片机AD采样-LCD1602液晶显示程序/******************************************************STC12C5A32S2或STC12C5A60S2等单片机ADC采样功能示例**1、P1口为8路10位AD转换口2、用LCD1602显示:数据口为P0,RW接P2.5,RS接P2.6,EN接P2.73、亲手编写、亲自调试,完全可行*****************************************************/#include#include#define uchar unsigned char#define uint unsigned intvoid delay_ms(uint x); //ms延时子函数/*****stc12c5a32s2相关的寄存器说明*****/sfr P1ASF = 0x9D; //P1口模数转换功能控制寄存器sfr ADC_CONTR = 0xBC; //AD转换控制寄存器sfr ADC_RES = 0xBD; //AD转换结果寄存器高位sfr ADC_RESL = 0xBE; //AD转换结果寄存器低位sfr AURX1 = 0xA2; //AD转换结果存储方式控制位/***P1ASF寄存器:8位,对应P1口8根线,用于指定那根线用作ADC功能******哪根线用作ADC就应置相应的位为1,注意:不能位寻址******/#define ADC_POWER 0x80 //ADC电源开#define ADC_SPEED 0x40 //设置为180个周期,ADC一次#define ADC_START 0x08 //ADC启动控制位设为开#define ADC_FLAG 0X10 //ADC结束标志位//***第n通道ADC初始化函数***//void ADC_int(uchar n){n &= 0x07; //确保是第0~7通道AURX1 |= 0x04; //转换结果存储方式:高2位放ADC_RES,低8位放ADC_RESL P1ASF = 1<<="">}//***第n通道ADC采样函数***//uint ADC_GET(uchar n){uint adc_data;n &= 0x07; //确保是第0~7通道ADC_RES = 0; //清存放结果存储器ADC_RESL = 0; //清存放结果存储器ADC_CONTR = 0; //AD转换控制寄存器清0,以便重置ADC_CONTR |= (ADC_POWER|ADC_SPEED|n|ADC_START);//打开AD转换电源,设定转换速度,设定通道号,AD转换开始_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//延时4个时钟周期左右while(!((ADC_CONTR & ADC_FLAG) == 0x10)) //等待转换结束adc_data = (ADC_RES & 0x03) * 256 + ADC_RESL; //转换结果计算ADC_CONTR &= 0xef; // 转换结束标志清0return adc_data; //adc_data的值(0~1023)}/***如果需要释放P1口为普通IO口,则需要本函数***//*void ADC_END(){P1ASF = 0;P1_CONTR = 0;}*//********延时子函数:xms********/void delay_ms(uint x){uint y;for(;x>0;x--)for(y=0;y<125;y++);}/*****以下是与LCD1602显示相关的定义和函数声明*****/#define lcd_data_port P0 //1602数据口接P0sbit lcd_rs = P2^6; //RS接P2.6(=0,是命令;=1,是数据)sbit lcd_rw = P2^5; //RW接P2.5(=0,是写;=1,是读)sbit lcd_en = P2^7; //EN接P2.7void lcd_write_com(uchar lcd_com); //写命令子函数void lcd_write_data(uchar lcd_data);//写数据子函数void lcd_int(); //1602初始化void lcd_locate(uchar x,uchar y); //显示定位(行,列)void lcd_4_char(uint data_4char); //显示4位整型函数/********写命令子函数********/void lcd_write_com(uchar lcd_com){lcd_data_port = lcd_com; //指令送到数据接口lcd_rs = 0; //选择命令lcd_rw = 0; //选择写lcd_en = 0;delay_ms(1);lcd_en = 1;delay_ms(1);lcd_en = 0;}/********写数据子函数********/void lcd_write_data(uchar lcd_data){lcd_data_port = lcd_data; //数据送到数据接口lcd_rs = 1; //选择数据lcd_rw = 0; //选择写lcd_en = 0;delay_ms(1);lcd_en = 1;delay_ms(1);lcd_en = 0;}/********LCD1602液晶初始化********/void lcd_int(){lcd_rs = 0; //选择命令lcd_rw = 0; //选择写lcd_en = 0;lcd_write_com(0x38); //设1602工作于16*2、5*7,8位数据接口模式lcd_write_com(0x0c); //开显示,不显示光标lcd_write_com(0x06); //写一个字符后,光标自动加一lcd_write_com(0x01); //清屏}/******显示定位子函数(行,列)******/void lcd_locate(uchar x,uchar y){uchar add;if(x == 1) add = 0x80;if(x == 2) add = 0x80+0x40;lcd_write_com(add+y-1);}/*********显示4位整数子函数********/void lcd_4_char(uint data_4_char){uchar lcd_table[4];lcd_table[1] = data_4_char / 1000; //获得千位lcd_table[2] = data_4_char % 1000 /100;//获得百位lcd_table[3] = data_4_char % 100 / 10; //获得十位lcd_table[4] = data_4_char % 10; //获得个位lcd_write_data(lcd_table[1] + 0x30); //显示千位lcd_write_data(lcd_table[2] + 0x30); //显示百位lcd_write_data(lcd_table[3] + 0x30); //显示十位lcd_write_data(lcd_table[4] + 0x30); //显示个位}/**************主函数***************/void main(){lcd_int(); //液晶初始化lcd_write_com(0x01); //液晶清屏while(1){uint ad_0 = 0;ADC_int(0); //ADC的通道0初始化ad_0 = ADC_GET(0); //AD转换处理后的数据存放于ad_0中lcd_locate(1,1); //显示在液晶的第1行,第1列lcd_4_char(ad_0); //显示4位整数delay_ms(20); //延时}}。
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电源稳定}/*。
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);}}如有侵权请联系告知删除,感谢你们的配合!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*---------------------------------------------------------------------------------------------------------------------------*/ /*--************************功能【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. "};//第一行显示框架unsigned char pos_char_table[] = {" D "};// 显示位置unsigned char Lcd_Dis2_table[] = {"Voltage : V"};//第二行显示框架unsigned char num_char_table[] = {" 9A.CD V"};// 显示位置sbit lcd_rs_port = P2^7; //定义LCD控制端口,根据硬件调整sbit lcd_rw_port = P2^6;sbit lcd_en_port = P2^4;#define lcd_data_port P0void lcd_delay(uchar ms);//LCD1602 延时void lcd_busy_wait(); //LCD1602 忙等待void lcd_command_write(uint command); //LCD1602 命令字写入void lcd_system_reset();//LCD1602 初始化void lcd_char_write(uint x_pos,y_pos,lcd_dat); //LCD1602 字符写入void lcd_bad_check(); //LCD1602 坏点检查void Num_to_Disp(uchar i, uint Num);//显示数据处理void LcdDisp(uchar j, uint num);//液晶显示函数/*------------------------以下为ADC相应寄存器初始化及端口定义-------------*//***** 定义与ADC相关的特殊功能寄存器*****/sfr ADC_CONTR = 0xBC; //ADC控制寄存器sfr ADC_RES = 0xBD; //ADC hight 8-bit result registersfr ADC_RESL = 0xBE; //ADC low 2-bit result registersfr P1ASF = 0x9D; //P1口功能控制寄存器P1ASF/************定义相应操作位***************/#define ADC_POWER 0x80 //ADC电源控制位,0:关闭,1:打开#define ADC_FLAG 0x10 //ADC结束标志位#define ADC_START 0x08 //ADC启动控制位#define ADC_SPEEDLL 0x00 //540 clocks___________选择转换速度/*------------------------以下为相关函数声明------------------------------*/void InitADC();//ADC初始化uint GetADCResult(uchar ch);void Delay(uint n); //延时程序void delay_1ms(uchar x);/*--------------------------------主函数--------------------------------*/void main(){uchar i;lcd_system_reset(); //LCD1602 初始化lcd_bad_check(); //LCD1602 坏点检查InitADC(); //初始化ADC特殊功能寄存器while (1){i = 0;while(i < 7){LcdDisp(i, GetADCResult(i)); //液晶1602显示输入电压值(P1.0 - P1.7)Delay(1000);i++;}}}/*-------------------------------- ADC 取值------------------------------*/uint GetADCResult(uchar ch){ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;_nop_(); //Must wait before inquiry_nop_();_nop_();_nop_();while (!(ADC_CONTR & ADC_FLAG)); //Wait complete flagADC_CONTR &= ADC_FLAG; //Close ADCreturn (ADC_RES*4 + ADC_RESL); //Return ADC result}/*----------------------------初始化ADC特殊功能寄存器-------------------*/void InitADC( ){P1ASF = P1 | 0x3f; //Set P1.0 - P1.5 as analog input portADC_RES = 0; //Clear previous resultADC_RESL = 0;ADC_CONTR = ADC_POWER | ADC_SPEEDLL ;Delay(20); //ADC power-on delay and Start A/D conversion }/*---------------------------- LCD1602相应函数---------------------------*////////////////以下为LCD显示数据处理/////////////////void Num_to_Disp(uchar i, uint Num){float NUM;int xx, yy, zz;NUM = (Num * 5/ 1024.0);//计算公式:10-bit A/D Conversion Result = 1024 x (Vin / Vcc) xx = (int)NUM;yy = (int)((NUM - (float)(xx)) * 10);zz = (int)((NUM - (float)(xx)) * 100)%10;num_char_table[9] = data_char_table[xx / 10];//电压值十位num_char_table[10]= data_char_table[xx % 10];//电压值个位num_char_table[12]= data_char_table[yy];//电压值小数点后一位num_char_table[13]= data_char_table[zz];//电压值小数点后两位?pos_char_table[13]= data_char_table[i];//当前ADC接口}//////////////////以下为LCD显示////////////////////void LcdDisp(uchar j, uint num){uint i=0;for (i=0;i<16;i++){lcd_char_write(i,0,Lcd_Dis1_table[i]);lcd_char_write(i,1,Lcd_Dis2_table[i]); //显示框架}Num_to_Disp(j, num);lcd_char_write(13,0,pos_char_table[13]);for(i = 9; i < 14; i++){lcd_char_write(i,1,num_char_table[i]); //显示电压}delay_1ms(100);}//////////////以下是LCD1602驱动程序////////////////void lcd_delay(uchar ms) /*LCD1602 延时*/{uchar j;while(ms--){for(j=0;j<250;j++){;}}}void lcd_busy_wait() /*LCD1602 忙等待*/{lcd_rs_port = 0;lcd_rw_port = 1;lcd_en_port = 1;lcd_data_port = 0xff;while (lcd_data_port&0x80);lcd_en_port = 0;}void lcd_command_write(uint command) /*LCD1602 命令字写入*/ {lcd_busy_wait();lcd_rs_port = 0;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = command;lcd_en_port = 1;lcd_en_port = 0;}void lcd_system_reset() /*LCD1602 初始化*/{lcd_delay(20);lcd_command_write(0x38);lcd_delay(100);lcd_command_write(0x38);lcd_delay(50);lcd_command_write(0x38);lcd_delay(10);lcd_command_write(0x08);lcd_command_write(0x01);lcd_command_write(0x06);lcd_command_write(0x0c);}void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/ {x_pos &= 0x0f; /* X位置范围0~15 */y_pos &= 0x01; /* Y位置范围0~ 1 */if(y_pos==1) x_pos += 0x40;x_pos += 0x80;lcd_command_write(x_pos);lcd_busy_wait();lcd_rs_port = 1;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = lcd_dat;lcd_en_port = 1;lcd_en_port = 0;}void lcd_bad_check() /*LCD1602 坏点检查*/{char i,j;for(i=0;i<2;i++){for(j=0;j<16;j++) {lcd_char_write(j,i,0xff);}}lcd_delay(200);lcd_delay(200);lcd_delay(200);lcd_delay(100);lcd_delay(200);lcd_command_write(0x01); /* clear lcd disp */}//////////////////以上是LCD1602驱动程序/////////////////*-----------------------------延时程序---------------------------*/ void Delay(uint n){uint x;while (n--){x = 500;while (x--);}}/*1MS为单位的延时程序*/void delay_1ms(uchar x){uchar j;while(x--){for(j=0;j<125;j++){;}}}。