简易12684液晶和Atmega32的电子万年历

发布者:CuriousTraveler最新更新时间:2013-12-12 来源: eefocus关键字:12684液晶  Atmega32  电子万年历 手机看文章 扫描二维码
随时随地手机看文章

闲来无事,又逢刮风下雨,把以前买来驱动一下就扔一边的12864液晶做个小万年历。哈哈……房间真差个钟~

所用的原件不多:

1.Atmega32单片机一个(其实At89s51足够,手头Atmega32最多,所以高成本一下吧)

2.晶振,电容22pF

3.7805,电容470uF,104若干,DC2.1电源插头。

4.DS1302,32768Hz晶振,2012电池(座)(其他的电源都行,用作备用电源)

5.12864液晶,带背光。

6.万用板一块。

先上图吧:

液晶背面就是主板了,这样结构容易站立。也挺美观。

再来一张,关灯的效果,看上去很幽暗恐怖……:

以下是程序(包括了DS1302驱动和12864液晶驱动)[page]

//端口配置是这样的:液晶的DB0-DB7数据口连接在单片机的PA口。

//液晶直接定义成并口方式,所以也就的PSB直接接高电平,低电平是串行方式。

//头文件包含
#include         //io端口寄存器配置文件,必须包含
#include        //GCC中的延时函数头文件
#include
//端口位定义
#define RS PC2          //数据/命令控制端 0命令,1数据
#define RW PC1           //读/写选择控制端 0写,1读
#define E PC0            //使能端          下降沿读,高电平写
//#define PSB PC7          //数据传输方式选择端,H,8位或4位并口方式;L,串口方式

//常量声明
#define BAUD 115200
#define TURE 1
#define FALSE 0
//时钟/日历寄存器
#define RD    0x01         //读
#define WR    0x00         //写
#define SECOND  0x80 //秒
#define MINUTE  0x82 //分
#define HOUR  0x84 //时
#define DAY   0x86 //日
#define MONTH  0x88 //月
#define WEEK  0x8A //星期 DATE
#define YEAR  0x8C //年
#define WR_PROTECT 0x8E //控制(写保护)
#define CHARGE     0x90 //涓流充电
#define BURST  0xBE //时钟多字节
//配置位
#define CLK_HALT  0x80 //停止时钟控制位    SECOND bit7
#define CLK_START  0x00 //启动时钟
#define M12_24   0x80 //12/24小时值选择位 HOUR  bit7
#define PROTECT   0x80 //写保护控制位      CONTROL bit7
#define UPROTECT  0x00 //写保护控制位      CONTROL bit7
//涓流充电控制常量
#define TC_D1R2   0xA5 //充电时选择一个二极管和2K电阻 
#define TC_D2R8   0xAB //充电时选择二个二极管和8K电阻  
#define TC_DISABLED  0x00 //禁止充电功能
//RAM 命令
#define RAMBASE  0xC0 //RAM起始位为0XCO,RAM范围0-31

//全局变量声明
unsigned char Get_Time[7] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};

//全局变量声明
unsigned char logo[]="==小电子万年历==";

//函数声明
void Delayus(unsigned int lus);         //us延时函数
void Delayms(unsigned int lms);        //ms延时函数
unsigned char DS1302_ReadByte(void);         //从DS1302读一个字节数据
void DS1302_WriteByte(unsigned char dat);    //向DS1302写一个字节数据
unsigned char DS1302_ReadData(unsigned addr); //从DS1302的指定地址读一个字节数据
void DS1302_WriteData(unsigned char addr,unsigned data); 
                                                 //向DS1302的指定地址写一个字节数据
void DS1302_SetTime(unsigned char *time);  //对DS1302设置时间
void DS1302_GetTime(void);   //从DS1302读取时间
unsigned char DS1302_Check(void);           //DS1302是否工作检测
void DS1302_Init(void);                      //DS1302初始化
void DS1302_DisCharge(void); //关闭涓流充电
unsigned char DS1302_Alarm(unsigned char hour,unsigned char min); //闹铃
void System_Beep(void);

void Port_Init(void);   //端口初始化
void LCD_Init(void);    //LCD初始化
void Write_Com(unsigned char LCD_Com);   //LCD写指令
void Write_Data(unsigned char LCD_Data);  //LCD写数据
void Check_Busy(void);   //读写检测函数,每次对液晶操作前都要进行读写检测
void Put_CHS_String(unsigned char x,unsigned char y,char *STR);

int main(void)           
{
 unsigned char Disp_Number;
 char str_time[64];
 unsigned char Set_Time[7] = {0x30,0x57,0x20,0x12,0x04,0x01,0x10};
                               //设置秒,分,时,日,月,星期,年
 char chs_week[7][6]={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
 _delay_ms(200);

 Port_Init();   //端口初始化
 LCD_Init();    //LCD初始化

 DS1302_DisCharge();
 DS1302_GetTime();
 if(Get_Time[2] == 0x00)
  DS1302_SetTime(Set_Time);

 Put_CHS_String(0,0,logo);
 DS1302_GetTime();
 
 Put_CHS_String(0,1,"现在时间:");
 while(1)
 {
  sprintf(str_time,"20%01x%01x年%01x%01x月%01x%01x日",Get_Time[6] / 16,Get_Time[6] % 16
                     ,Get_Time[4] / 16,Get_Time[4] % 16
                     ,Get_Time[3] / 16,Get_Time[3] % 16 );
  Put_CHS_String(0,2,str_time);
 
  sprintf(str_time,"星期%01x %01x%01x:%01x%01x:%01x%01x",Get_Time[5] % 16        
                  ,Get_Time[2] / 16,Get_Time[2] % 16
                     ,Get_Time[1] / 16,Get_Time[1] % 16
                     ,Get_Time[0] / 16,Get_Time[0] % 16 );
  Put_CHS_String(0,3,str_time);
 
  DS1302_GetTime();
  _delay_ms(500);
 
 }

}

void Port_Init()
{     
 //LCD数据端口设置
 PORTA = 0X00;         //
 DDRA = 0XFF;           //配置端口PA全部为输出口,LCD数据端口
 
 PORTD = 0X00;
 DDRD |= 1< PORTD |= 1< 
 //LCD控制端口设置
 PORTC = 0X00;         //
 DDRC |= (1 << RS) | (1 << RW) | (1 << E);

 PORTB = 0XFF;
 DDRB |= (1 << PB1) | (1 << PB0); //DS1302的IO和SCLK引脚设为输出
 DDRB |= (1 << PB2);                //DS1302的RST引脚设为输出

}

void LCD_Init()
{
 Write_Com(0X01);  //清屏
 _delay_us(5);
 Write_Com(0X38);  //显示模式设置 16x2显示,5x7点阵,8位数据接口
 _delay_us(5);
 //Write_Com(0X0f);  //显示开关控制,开显示,光标显示,光标闪烁
 Write_Com(0X0c);  //显示开关控制,开显示,光标不显示,光标不闪烁
 _delay_us(5);
 Write_Com(0X06);  //光标设置,读或写一个字符后,地址指针加一,光标加一,整屏不移动
 _delay_us(5);
}

void Write_Com(unsigned char LCD_Com)
{
 Check_Busy();
 
 PORTC &= ~(1 << RS);     //RS=0,写命令
 PORTC &= ~(1 << RW);     //RW=0,写指令
 PORTC |= (1 << E);       //E=1,写操作
 _delay_us(5);
 PORTA = LCD_Com;         //指令送数据端口
 PORTC &= ~(1 << E);     //E=0,停止写操作
 _delay_us(5);
 
}

void Write_Data(unsigned char LCD_Data)
{
 Check_Busy();

 PORTC |= (1 << RS);      //RS=1,写数据
 PORTC &= ~(1 << RW);    //RW=0,写指令
 PORTC |= (1 << E);      //E=1,写操作
 _delay_us(5); 
 PORTA = LCD_Data;        // 数据送数据端口  
 PORTC &= ~(1 << E);    //E=0,停止写操作
 _delay_us(5);
 
}

void Check_Busy()
{
    
 DDRA = 0X00;             //PA口置为输入口,准备读取数据
 PORTC &= ~(1 << RS);      //RS=0,读命令
 PORTC |= (1 << RW);    //RW=1,读指令
 PORTC |= (1 << E);      //E=1,使能
 
 while(0X80 & PINA);   //监测忙信号,直到忙信号为0,才能进行读写操作
 PORTC &= ~(1 << E);   //E=0
 DDRA = 0XFF;          //PA口置为输出口,准备向端口发送数据
}

void Put_CHS_String(unsigned char x,unsigned char y,char *STR)
{
 unsigned char Disp_Number;
 switch(y)
 {
  case 0:
   Write_Com(0X80+x);
   break;
  case 1:
   Write_Com(0X90+x);
   break;
  case 2:
   Write_Com(0X88+x);
   break;
  case 3:
   Write_Com(0X98+x);
   break;
  default:
   break;
 }
 for(Disp_Number = 0;Disp_Number < strlen(STR);Disp_Number++)
 {
  Write_Data(STR[Disp_Number]);
  _delay_us(5);
 }
}[page]

/**********************************************/

//从DS1302读一个字节数据
unsigned char DS1302_ReadByte(void)        
{
 unsigned char i,dat = 0;  //dat存放读出的数据,初始化为0
 PORTB &= ~(1 << PB1);     //DS1302的I/O口上拉不使能,
 DDRB &= ~(1 << PB1);      //DS1302的I/O口设置为输入口,准备读数据
 
 for(i = 0;i < 8;i++)     //读8位,低位在前,右移
 {
  dat >>= 1;           //读出的数据右移一位
  PORTB |= (1 << PB0);  //DS1302的SCLK端口拉高
  Delayus(10);          //
  PORTB &= ~(1 << PB0);  //DS1302的SCLK端口拉低,产生下降沿,
  Delayus(10);
  if(PINB & (1 << PB1))     //读数据端口状态
  {
   dat |= 0x80;          //如果数据端口位高,相应数据位置1
  } 
 }
 DDRB |= (1 << PB1);   //最后将数据端口设置为输出
    return dat;     //返回读出的数据
}

//向DS1302写一个字节数据
void DS1302_WriteByte(unsigned char dat)   
{
 unsigned char i;
 
 for(i = 0;i < 8;i++)      //写8位,低位在前
 {
  PORTB &= ~(1 << PB0);  //DS1302的SCLK置低
  if(dat & 0x01)        //写数据位
  {
   PORTB |= (1 << PB1);   //如果该位为1,则I/O口置高
  }
  else
  {
   PORTB &= ~(1 << PB1);   //如果该位为0,则I/O口置低
  }
  Delayus(10);          //
  PORTB |= (1 << PB0);   //DS1302的SCLK置高,产生上升沿
  dat >>= 1;               //数据右移1位
 } 
}

//从DS1302的指定地址读一个字节数据
unsigned char DS1302_ReadData(unsigned addr)
{
 unsigned char data;
 
 PORTB &= ~(1 << PB2); //拉低片选端
 PORTB &= ~(1 << PB0);//拉低时钟端
 Delayus(10);
 PORTB |= (1 << PB2);//拉高片选端
 Delayus(10);
 DS1302_WriteByte(addr);//写入操作命令(地址)
 Delayus(10);
 data = DS1302_ReadByte();//读出数据
 Delayus(10);
 PORTB &= ~(1 << PB0);  //拉低时钟端
 PORTB &= ~(1 << PB2); //拉低片选端 
 
 return data;
}

//向DS1302的指定地址写一个字节数据
void DS1302_WriteData(unsigned char addr,unsigned data) 
{
 PORTB &= ~(1 << PB2); //拉低片选端
 PORTB &= ~(1 << PB0);//拉低时钟端
 Delayus(10);
 PORTB |= (1 << PB2);//拉高片选端
 Delayus(10);
 DS1302_WriteByte(addr);//写入操作命令(地址)
 Delayus(10);
 PORTB &= ~(1 << PB0);//拉低时钟端
 Delayus(10);
 DS1302_WriteByte(data);//写入数据
 PORTB &= ~(1 << PB0);  //拉低时钟端

 Delayus(10);
 PORTB &= ~(1 << PB2); //拉低片选端
}

//对DS1302设置时间           
void DS1302_SetTime(unsigned char *time) 
{
 unsigned char i;
 unsigned char addr = 0x80;//写入地址从秒寄存器开始
 
 DS1302_WriteData(WR_PROTECT | WR,UPROTECT);//控制命令,WP位为0,允许写操作
 Delayms(5);
 for(i = 0;i < 7;i++)
 {
  DS1302_WriteData(addr | WR,time[i]);// 秒 分 时 日 月 星期 年  
  addr += 2;
  Delayms(1);
 }
 DS1302_WriteData(WR_PROTECT | WR,PROTECT);//控制命令,WP位为1,不允许写操作   
}

//从DS1302读取时间
void DS1302_GetTime(void)  
{
 unsigned char i;
 PORTB &= ~(1 << PB2);
 Delayus(10);
 PORTB |= (1 << PB2);
 Delayus(10);
 DS1302_WriteByte(0xbf);
 for(i = 0;i < 8;i++)
 {
  Get_Time[i] = DS1302_ReadByte();
 }
 PORTB &= ~(1 << PB2);
 PORTB &= ~(1 << PB0);
}

//DS1302是否工作检测
unsigned char DS1302_Check(void)          
{
 DS1302_WriteData(WR_PROTECT | WR,UPROTECT);
 DS1302_WriteData(RAMBASE | WR,0x31);
 
 if(DS1302_ReadData(RAMBASE | WR) == 0x31)
 {
  return TURE;
 }
 else
 {
  return FALSE;
 }
}

void DS1302_DisCharge(void)
{
 DS1302_WriteData(CHARGE|WR,TC_DISABLED);
 Delayus(10);
}

unsigned char DS1302_Alarm(unsigned char hour,unsigned char min)
{

}

void System_Beep(void)
{

}

//DS1302初始化
void DS1302_Init(void)
{
 DS1302_WriteData(WR_PROTECT | WR,UPROTECT);   //写入写允许命令
 DS1302_WriteData(SECOND | WR,CLK_START);      //启动振荡器,DS1302开始工作
 DS1302_WriteData( WR_PROTECT | WR,PROTECT);     //控制命令,WP位为1,不允许写操作   
}


//us级别的延时函数
void Delayus(unsigned int lus)
{
 while(lus--)
 {
  _delay_loop_2(3);      //_delay_loop_2(1)是延时4个时钟周期,参数为3则延时12
             //个时钟周期,本实验用12M晶体,则12个时钟周期为12/12=1us
    }
}

//ms级别的延时函数
void Delayms(unsigned int lms)
{
 while(lms--)
 {
  Delayus(800);        //延时1ms
    }
}

关键字:12684液晶  Atmega32  电子万年历 引用地址:简易12684液晶和Atmega32的电子万年历

上一篇:AVR单片机Atmega128外扩RAM
下一篇:关于ATMEGA32的TWI使用

推荐阅读最新更新时间:2024-03-16 13:32

采用Atmega32单片机车门压力测试仪制作
车门压力测试仪为便携手持式结构,采用专用压力测试传感器和测试管理系统组成,专门用于检测地铁车辆客室车门关紧力、最小障碍物探测,及车门防夹保护功能检测。设备能够设置和记录开关门次数、时间、试验项目,系统可以自动有效的完成试验要求并自动记录试验结果生成报表。 车辆车门尤其是列车等高速运行车辆的车门是一个安全性能要求较高的产品,其各项性能指标必须保持在一个相对安全的取值范围内,以保证车辆的安全运行。这不仅要求制造厂家在产品制造过程中需要测试这些参数,同时在产品投入使用后的检修保养过程中也需要检测这些参数,做为产品的安全使用提供必要的参考信息;长期以来,由于我国对检测仪器的研制重视不够,通常的检测手段主要是靠检测人员借助多种手工工具辅
[测试测量]
采用<font color='red'>Atmega32</font>单片机车门压力测试仪制作
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
502 Bad Gateway

502 Bad Gateway


openresty
设计资源 培训 开发板 精华推荐

502 Bad Gateway

502 Bad Gateway


openresty
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

502 Bad Gateway

502 Bad Gateway


openresty
502 Bad Gateway

502 Bad Gateway


openresty
502 Bad Gateway

502 Bad Gateway


openresty
随便看看
    502 Bad Gateway

    502 Bad Gateway


    openresty
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
502 Bad Gateway

502 Bad Gateway


openresty