12864+内部AD+eeprom.docx
《12864+内部AD+eeprom.docx》由会员分享,可在线阅读,更多相关《12864+内部AD+eeprom.docx(22页珍藏版)》请在冰豆网上搜索。
12864+内部AD+eeprom
实验名称:
简易数字电压表。
(测试范围0——5V,如需加大范围,改变相关数据类型,鉴于STC12C5A60S2内部AD的特性,有相当误差)
实验目的:
通过STC12C5A60S2自带AD采集外部电压,将采集到的AD值传给LCD12864。
单片机上电后如未接入任何电压,将显示上次输入电压
实验手段:
STC12C5A60S2单片机内部AD、内部EEPROM、LCD12864(ks108控制器,不带字库)、DD900开发板
实验原理图:
其中P1.0为电压输入端,电压输入引出一根杜邦线即可。
(主要接法)(补充接法)
说明:
DD900开发板在VEE端接的电阻值只匹配他们店自带的12864(不带字库型),实验结果模糊不可见。
原因是对比度不够,也就是VO端电压不匹配。
实验电路主要参考左图,对VO端、VEE端接法请参考补充接法。
实际电路电阻值接50K,事实上可自我调节阻值大小。
实验结果:
基本完成每个模块的功能。
不足之处:
现实运用中,电压表测量电压时,如果没有输入的话,电压表应显示为0,本实验结果是未输入时,电压飘忽不定。
原因:
AD采集数据不稳定的原因是因为未输入时电压输入通道为悬空状态,AD默认为电压不定,所以会出现上述状况。
在有电压输入的时候,状况良好,漂移少见。
因为加入EEPROM模块,本想把悬空状态给和谐掉。
我也尝试两者间不同(悬空的时候变化剧烈,时刻变化,是否可以用程序的方法和谐?
?
),事实上我试了一个程序思路,发现液晶数值即使在稳定状态,也可能不仅仅是前后两次对比的结果,可能是多次的结果,由于液晶显示需要一定的时间,这样的话,只需要隔一定时间保持相同的值与最先采集的值相等即可。
本程序采用的是50次AD结果计算平均值,如需更加稳定,可以考虑中值平滑滤波算法。
各个子模块介绍:
STC12C5A60S2内部自带AD.
IO初始化+AD初始化+AD采集开始+关闭AD(AD电源也可不关闭,省电下可考虑)
IO初始化:
STC12c5a60s2内部AD的八个通道在P1口,上电默认为输入输出准双向口模式。
使用AD时要先将IO口设置为AD输入模式。
对P1M0/P1M1寄存器进行操作
AD初始化:
ADC_CONTR(特别要注意的地方是每给ADC_CONTR赋值操作需要4个nop指令)
1)对P1口八个口中那个口设置为AD输入通道(可设置为多个通道,但处理时还是一路一路),即对上图ADC_CONTR中CHS2CHS1CHS0进行设置。
2)ADC上电。
仅仅以为打开AD电源,并没有开始转换。
ADC_POWER。
3)对结果寄存器REL/RESL清零。
4)通过设置SPEED1SPEED0来设置四种不同AD采集的速度。
与晶振相关。
AD采集开始:
设置ADC_START的值为1。
ADC-FLAG:
ADC中断标志位,如需采用中断方式,AD采集后FLA置1,需软件清零。
下面是AD模块程序:
/********************************************************
********************单片机IO(AD)初始化****************/
voidIO_ADinit()
{
P1M0|=0x01;//设P1_0为开漏模式如:
P1_0=#00000000B
P1M1|=0x01;
ADC_CONTR=0xe0;//设置P1.0为输入AD转换口
_nop_();//ADC_CONTR需要四个指令延时
_nop_();
_nop_();
_nop_();
}
/********************************************************
*******************AD上电*******************************/
voidADC_Power_On()
{
ADC_CONTR|=0x80;
_nop_();
_nop_();
_nop_();
_nop_();//ADC_CONTR需要四个指令延时
}
/********************************************************
********************AD转换获取AD值***********************/
voidget_ad_result()//取AD结果函数。
{
uinti,q=0;
for(i=0;i<10;i++)//AD转换循环10次取平均值
{
tp=0;
ADC_RES=0;//高八位数据清零,STC12C5A60S2
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转换调用程序*************************/
voidADCONVERT()
{
ADC_Power_On();
IO_ADinit();
get_ad_result();
}
STC12C5A60S2内部EEPROM介绍
原理:
运用ISP/IAP技术将内部FLASH当作EEPROM来用。
规格大小:
手册上仅有12C560S2,可能漏写A。
内部EEPROM存储空间为1K.。
注意事项:
在进行EEPROM操作时,一般应将EA=0,待数据处理完毕再打开中断。
使用:
打开IAP、从EEPROM处读数据、写数据、擦除扇区(每进行一次写操作,都要进行擦除)、关闭IAP。
IAP_CMD命令中需要变化的只有MS1MS0也就是下图的B1B0;三个操作:
读、写、擦。
IAP_TRIG:
如果用到IAP_CMD这个命令的话,要想它动作,必须给IAP_TRIG赋值如下来触发。
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
IAP_CONTR:
WT2/WT1/WT0三个参数设置。
内部EEPROM完成读写擦操作所需时间,根据所接晶振设置。
IAPEN;
IAPEN=1,允许FLASH编程。
在打开IAP的时候要置1;
IAPEN=0,不允许FLASH编程。
下面是IAP模块程序。
/**函数名:
Open_IAP*
功能描述:
允许ISP/IAP*/
voidOpen_IAP(void)
{
EA=0;//防止被中断打断
IAP_CONTR=0x80;//充许ISP/IAP,系统时钟<20MHz时,设置等待时间WT2,WT1,WT0(010)
}
/**函数名:
Close_IAP
*功能描述:
禁止ISP/IAP*/
voidClose_IAP(void)
{
IAP_CONTR=0x00;//禁止ISP/IAP
IAP_ADDRH=0xFF;//将IAP操作地址的高八位与低八位移到非本次操作地址处(防止IAP误操作)
IAP_ADDRL=0xFF;
EA=1;
}
/**函数名:
Read_IAP_Byte
*功能描述:
从EEPROM指定的单元读取一个字节数据*/
uintRead_IAP_Byte(uintaddr)
{
IAP_CMD=0x01;
IAP_ADDRH=(addr&0xFF00)>>8;
IAP_ADDRL=addr&0x00FF;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;//对IAP_TRIG先写0x5A再写0xA5,ISP/IAP命令才会生效
returnIAP_DATA;
}
/**函数名:
Write_IAP_Byte
*功能描述:
把一个字节数据写入EEPROM指定的单元,写入数据前应先擦除扇区
*输入参数:
addr:
16bit地址;writeVal:
要写入的数据*/
voidWrite_IAP_Byte(intaddr,uintwriteVal)
{
IAP_CMD=0x02;
IAP_ADDRH=(addr&0xFF00)>>8;
IAP_ADDRL=addr&0x00FF;
IAP_DATA=writeVal;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;//对IAP_TRIG先写0x5A再写0xA5,ISP/IAP命令才会生效
}
/**函数名:
Erase_IAP_Sector
*功能描述:
擦除扇区,没有字节擦除
*输入参数:
addr:
扇区地址,扇区中任意一个字节地址都是该扇区地址*/
voidErase_IAP_Sector(intaddr)
{
IAP_CMD=0x03;
IAP_ADDRH=(addr&0xFF00)>>8;
IAP_ADDRL=addr&0x00FF;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;//对IAP_TRIG先写0x5A再写0xA5,ISP/IAP命令才会生效
}
关于12864模块
这个模块我就不说了,网上程序一大堆,原理图也有。
我遇到的问题是对比度调节(硬件连接不对,上有提到)。
如果显示一部分,应该是延时问题。
加延时或者减少晶振先验证一下。
整个程序的源代码:
(有待规范跟完善)
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLcd_BusP0//MCUP0<------>LCM
#defineDisp_On0x3f//开显示
#defineDisp_Off0x3e//关显示
#defineCol_Add0x40//列地址
#definePage_Add0xb8//页地址
#defineStart_Line0xc0//起始页
sbitcs1=P2^3;//Masterchipenable
sbitcs2=P2^4;//Slavechipenable
sbitEnable=P2^2;//modeEnablesingle
sbitDi=P2^0;//DataorInstrumentSelect
sbitRW=P2^1;//WriteorRead
sbitLcd_Rst=P2^5;//Lcmreset
unsignedinta,i,j,k;
unsignedchartp,p,plus;
uintVin,count;
uintad_average_result;
unsignedcharcodesz0[]={//数字08*16//
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,
};
unsignedcharcodesz1[]={//数字18*16//
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
};
unsignedcharcodesz2[]={//数字28*16//
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,
};
unsignedcharcodesz3[]={//数字38*16//
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,
};
unsignedcharcodesz4[]={//数字48*16//
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,
};
unsignedcharcodesz5[]={//数字58*16//
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,
};
unsignedcharcodesz6[]={//数字68*16//
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,
};
unsignedcharcodesz7[]={//数字78*16//
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,
};
unsignedcharcodesz8[]={//数字88*16//
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,
};
unsignedcharcodesz9[]={//数字98*16//
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,
};
unsignedcharcodesz11[]={0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00};
unsignedcharcodesz10[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00};
unsignedcharcode*shuzi[]={sz0,sz1,sz2,sz3,sz4,sz5,sz6,sz7,sz8,sz9,sz10};
/*****************************
字模,此字体下对应的
点阵为:
宽x高=16x16
*****************************/
unsignedcharcodeChinese_character[][32]=
{
{0x10,0x60,0x01,0xF6,0x00,0x10,0xF8,0x17,0x34,0x54,0x14,0x14,0xF4,0x04,0x04,0x00,0x04,0x04,0xFF,0x00,0x01,0x01,0x1F,0x11,0x13,0x15,0x51,0x91,0x7F,0x11,0x11,0x00},/*"海",0*/
{0x00,0x80,0x60,0xF8,0x0F,0x02,0xF8,0x08,0x0C,0x0B,0x0A,0x08,0x08,0xF8,0x00,0x00,0x01,0x00,0x00,0x7F,0x00,0x00,0x7F,0x21,0x21,0x21,0x21,0x21,0x21,0x7F,0x00,0x00},/*"伯",1*/
{0x00,0x00,0xF8,0x48,0x48,0x48,0x48,0xFF,0x48,0x48,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0x3F,0x44,0x44,0x44,0x44,0x4F,0x40,0x70,0x00},/*"电",2*/
{0x00,0x00,0x02,0x02,0x02,0x02,0x02,0xE2,0x12,0x0A,0x06,0x02,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x41,0x81,0x7F,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00},/*"子",3*/
{0x14,0x24,0x44,0x84,0x64,0x1C,0x20,0x18,0x0F,0xE8,0x08,0x08,0x28,0x18,0x08,0x00,0x20,0x10,0x4C,0x43,0x43,0x2C,0x20,0x10,0x0C,0x03,0x06,0x18,0x30,0x60,0x20,0x00},/*"欢",4*/
{0x40,0x41,0xCE,0x04,0x00,0xFC,0x04,0x02,0x02,0xFC,0x04,0x04,0x04,0xFC,0x00,0x00,0x40,0x20,0x1F,0x20,0x40,0x47,0x42,0x41,0x40,0x5F,0x40,0x42,0x44,0x43,0x40,0x00},/*"迎",5*/
{0x80,0x40,0x30,0xFC,0x03,0x90,0x68,0x06,0x04,0xF4,0x04,0x24,0x44,0x8C,0x04,0x00,0x00,0x20,0x38,0x03,0x38,0x40,0x40,0x49,0x52,0x41,0x40,0x70,0x00,0x09,0x30,0x00},
{0x00,0x00,0xF8,0x48,0x48,0x48,0x48,0xFF,0x48,0x48,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0x3F,0x44,0x44,0x44,0x44,0x4F,0x40,0x70,0x00},
{0x00,0x00,0xFE,0x02,0x42,0x42,0x42,0x42,0xFA,0x42,0x42,0x42,0x62,0x42,0x02,0x00,0x20,0x18,0x27,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x21,0x2E,0x24,0x20,0x20,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x80,0x40,0xf0,0x0f,0x22,0x20,0x20,0x20,0xff,0x22,0x20,0x22,0x2c,0x24,0x00,0x00,0x00,0x00,0x7f,0x00,0x40,0x20,0x18,0x06,0x01,0x02,0x0c,0x18,0x30,0x60,0x20,0x00},
};
/***********************延时子程序***********************/
voiddelay(unsignedintk)
{
unsignedinti;
unsignedintj;
for(i=0;ifor(j=0;j<20;j++);
}
/***********************写命令左***********************/
voidwrite_cmd_1(unsignedcharcommand)
{
cs1=1;cs2=0;
Di=0;
RW=0;
Lcd_Bus=command;
delay(0);
Enable=1;
delay(0);
Enable=0;
}
/***********************写命令右***********************/
voidwrite_cmd_2(unsignedcharcommand)
{
cs1=0;cs2=1;
Di=0;
RW=0;
Lcd_Bus=command;
delay(0);
Enable=1;
delay(0);
Enable=0;
}
/***********************写数据左***********************/
voidwrite_data_1(unsignedchardis_data)
{
cs1=1;cs2=0;
Di=1;
RW=0;
Lcd_Bus=dis_data;
delay(0);
Enable=1;
delay(0);
Enable=0;
}
/***********************写数据右***********************/
voidwrite_data_2(unsignedchardis_data)
{
cs1=0;cs2=1;
Di=1;
RW=0;
Lcd_Bus=dis_data;
delay(0);
Enable=1;
delay(0);
Enable=0;
}
/***********************清内存左***********************/
voidclear_1(void)
{
unsignedcharj,k;
cs1=1;cs2=0;
write_cmd_1(Page_Add+0);
write_cmd_1(Col_Add+0);
for(k=0;k<8;k++){
write_cmd_1(Page_Add+k);
for(j=0;j<64;j++)write_data_1(0x00);
}
}
/***********************清内存右***********************/
voidclear_2(void)
{
unsignedcharj,k;
cs1=0;cs2=1;
write_cmd_2(Page_Add+0);
write_cmd_2(Col_Add+0);
for(k=0;k<8;k++){
write_cmd_2(Page_Add+k);
for(j=0;j<64;j