继续假期写总结的习惯,开始每天总结。百度空间居然倒闭了,去年暑假写的VB日记全都没了,怪可惜的。今天看了了STC15单片机的时钟与复位部分。
STC15出厂时内配有片内RC振荡器时钟,不用再外焊晶振及滤波电容。当有特殊要求时可由XTAL1和XTAL2引脚外接晶振产生时钟信号,也可直接从XTAL1脚输入外部时钟信号,XTAL2脚悬空。
时钟源输出信号经过一个可编程时钟分频器与CPU、内部接口相连。片内RC振荡器或外接晶振产生的时钟称为主时钟,频率记为fosc。CPU和内部接口的时钟称为系统时钟,频率记为fsys。其关系为fsys=fosc/N。分频系数N可通过特殊功能寄存器CLK_DIV进行选择。其中CLKS2~CLKS0位为分频系统选择位。
STC15单片机的主时钟fosc可以通过P5.4引脚输出。
关于复位,分为冷启动和热启动。冷启动复位后上电复位标志位PDF为置1,可软件清0。其在PCON寄存器内。今天才知道单片机的寄存器地址不能被8整除便不可直接操作位,需要用与操作读取。例如上电复位标志位PDF在PCON寄存器中的D4位,即00010000。当读取其值时,用a=PCON&0x10;读取状态。若PDF为1则为系统停电后再上电引起的硬复位,为0则是RST引脚人为使单片机复位、内部看门狗产生复位或操作IAP_CONTR寄存器实现的代码复位。
STC15单片机在烧录器中可设置低电压检测值。当内部电压VCC低于低压检测门限电压时,PCON寄存器中LVDF将自动置1。可在烧录时选择LVDF置1时单片机复位或是申请中断停止程序。
今天对上电复位标志位比较感兴趣,还写了一个小测试程序,不管如何变化复位方式他的值都是1。贴上代码明天继续研究。
#include "stc15.h"
#include "096oled.h"
#include "font.h"
sbitOLED_SPI_SDIN=P1^5; //SPI通信数据线
sbitOLED_SPI_SCLK=P1^6; //SPI通信时钟线
sbitOLED_SPI_DC=P1^7; //SPI通信命令数据选择
sbitOLED_SPI_RST=P5^5; //OLED复位引脚
int angle,a; //临时变量;
void OledWriteByte(uchar wbyte,uchar cmd)
{
uchar i;
OLED_SPI_DC=cmd;
for(i=0;i<8;i++)
{
OLED_SPI_SCLK=0;
if(wbyte&0x80)
{
OLED_SPI_SDIN=1;
}
else
{
OLED_SPI_SDIN=0;
}
OLED_SPI_SCLK=1;
wbyte<<=1;
}
}
void OledInit(void)
{
OledWriteByte(SET_DISPLAY_OFF,OLED_CMD);
OledWriteByte(SET_DISPLAY_CLOCK,OLED_CMD);
OledWriteByte(0x80,OLED_CMD);
OledWriteByte(SET_MULTIPLEX_RATIO,OLED_CMD); //驱动路数设置命令
OledWriteByte(0x3F,OLED_CMD); //驱动路数值
OledWriteByte(SET_DISPLAY_OFFSET,OLED_CMD); //显示偏移设置命令
OledWriteByte(0x00,OLED_CMD); //取值范围:0x00-->0x3F
OledWriteByte(0x40,OLED_CMD); //取值范围:0x40---0x7F
OledWriteByte(CHARGE_PUMP_SET,OLED_CMD); //电荷泵设置命令
OledWriteByte(0x14,OLED_CMD); //开启电荷泵
OledWriteByte(SET_MEMORY_ADDR_MODE,OLED_CMD); //内存地址模式设置命令
OledWriteByte(0x10,OLED_CMD); //设置地址模式值:0x00,列地址模式;0x01,行地址模式;
//0x10,页地址模式;
OledWriteByte(SET_SEGMENT_REMAP_A1,OLED_CMD); //列地址0映射到SEG127
OledWriteByte(SET_COM_SCAN_DIRECTION_C8,OLED_CMD); //行地址0映射到COM63
OledWriteByte(SET_COM_PINS_CONFIG,OLED_CMD); //设置COM硬件引脚配置命令
OledWriteByte(0x12,OLED_CMD);
OledWriteByte(SET_CONTRAST_CONTROL,OLED_CMD); //对比度设置命令
OledWriteByte(0x8F,OLED_CMD); //对比度值,取值范围1-255
OledWriteByte(SET_PRECHARGE_PERIOD,OLED_CMD);
OledWriteByte(0xF1,OLED_CMD);
OledWriteByte(SET_VCOMH_DESELECT_L,OLED_CMD);
OledWriteByte(0x30,OLED_CMD);
OledWriteByte(ENTIRE_DISPLAY_ON_A4,OLED_CMD);
OledWriteByte(NORMAL_DISPLAY,OLED_CMD); //0:熄灭像素;1:点亮像素
OledWriteByte(SET_DISPLAY_ON,OLED_CMD);
OledClearn();
}
void OledClearn(void)
{
uchar i,j;
for(i=0;i<8;i++)
{
OledWriteByte(0xb0+i,OLED_CMD); //设置页地址
OledWriteByte(0x00,OLED_CMD); //设置列低地址
OledWriteByte(0x10,OLED_CMD); //设置列高地址
for(j=0;j<128;j++)
{
OledWriteByte(0x00,OLED_DATA);
}
}
}
void DisplayChar_12X06(uchar x,uchar y,uchar *dispdata)
{
uchar i,j,fontposition,addyl,addyh;
uchar *databuf;
while((*dispdata)!=0)
{
fontposition=*dispdata-0x20; //计算字符在字库中的位置
databuf=(uchar*)(ASCII_1206+fontposition); //获取字符点阵数据起始地址
addyl=y; //计算列低地址
addyh=y/16+0x10; //计算列高地址
for(i=0;i<2;i++)
{
OledWriteByte(0xb0+x+i,OLED_CMD); //设置页地址
OledWriteByte(addyl,OLED_CMD); //设置列低地址
OledWriteByte(addyh,OLED_CMD); //设置列高地址
for(j=0;j<6;j++)
{
OledWriteByte(*(databuf++),OLED_DATA);
}
}
y+=6; //列地址自加6
dispdata++;
}
}
void display(unsigned char y,unsigned char x,int a)
{
uchar a1,a2,a3; //个位
if(a<0)
{
DisplayChar_12X06(y,x,"-");
a=-a;
}
else DisplayChar_12X06(y,x," ");
a1=a/100; //百位数
a2=a0/10; //十位数
a3=a;
switch(a1)
{
case1:DisplayChar_12X06(y,x+6,"1");break; //1
case2:DisplayChar_12X06(y,x+6,"2");break; //2
case3:DisplayChar_12X06(y,x+6,"3");break; //3
case4:DisplayChar_12X06(y,x+6,"4");break; //4
case5:DisplayChar_12X06(y,x+6,"5");break; //5
case6:DisplayChar_12X06(y,x+6,"6");break; //6
case7:DisplayChar_12X06(y,x+6,"7");break; //7
case8:DisplayChar_12X06(y,x+6,"8");break; //8
case9:DisplayChar_12X06(y,x+6,"9");break; //9
default:DisplayChar_12X06(y,x+6,"0");break; //0
}
switch(a2)
{
case1:DisplayChar_12X06(y,x+12,"1");break; //1
case2:DisplayChar_12X06(y,x+12,"2");break; //2
case3:DisplayChar_12X06(y,x+12,"3");break; //3
case4:DisplayChar_12X06(y,x+12,"4");break; //4
case5:DisplayChar_12X06(y,x+12,"5");break; //5
case6:DisplayChar_12X06(y,x+12,"6");break; //6
case7:DisplayChar_12X06(y,x+12,"7");break; //7
case8:DisplayChar_12X06(y,x+12,"8");break; //8
case9:DisplayChar_12X06(y,x+12,"9");break; //9
default:DisplayChar_12X06(y,x+12,"0");break; //0
}
switch(a3)
{
case1:DisplayChar_12X06(y,x+18,"1");break; //1
case2:DisplayChar_12X06(y,x+18,"2");break; //2
case3:DisplayChar_12X06(y,x+18,"3");break; //3
case4:DisplayChar_12X06(y,x+18,"4");break; //4
case5:DisplayChar_12X06(y,x+18,"5");break; //5
case6:DisplayChar_12X06(y,x+18,"6");break; //6
case7:DisplayChar_12X06(y,x+18,"7");break; //7
case8:DisplayChar_12X06(y,x+18,"8");break; //8
case9:DisplayChar_12X06(y,x+18,"9");break; //9
default:DisplayChar_12X06(y,x+18,"0");break; //0
}
}
void main(void)
{
OledInit();
while(1)
{
a=PCON&0X10;
display(0,0,a);
}
}