姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx

上传人:b****7 文档编号:9037425 上传时间:2023-02-02 格式:DOCX 页数:20 大小:18.49KB
下载 相关 举报
姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx_第1页
第1页 / 共20页
姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx_第2页
第2页 / 共20页
姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx_第3页
第3页 / 共20页
姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx_第4页
第4页 / 共20页
姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx

《姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx》由会员分享,可在线阅读,更多相关《姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx(20页珍藏版)》请在冰豆网上搜索。

姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序.docx

姚磊基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序

 

//////////以下是DS1307头文件/////////////////////////////

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

#defineIIC_PORTPORTF//定义是使用PROTF口,定义scl连接的是PF1,定义sda连接的是PF0

#defineIIC_DDRDDRF//IIC_DDR&=SSDA;-设置SDA为输入口//IIC_DDR|=SDA;-设置SDA为输出口

#defineSCL0X02//IIC_PORT|=SCL;-scl置1

#defineSDA0X01//IIC_PORT|=SDA;-sda置1

#defineSSCL0XFD//IIC_PORT&=SSCL;-scl置0

#defineSSDA0XFE//IIC_PORT&=SSDA;-sda置0

uintaa[7];//定义一个数组以便接受数据

voiddelay(unsignedintus)

{while(us--);}

voidStart_I2C(void)

{

IIC_PORT|=SDA;//sda

IIC_PORT|=SCL;//scl

asm("nop");

IIC_PORT&=~SDA;

asm("nop");

IIC_PORT&=~SCL;

}

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

内部函数,I2C结束

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

voidStop_I2C(void)

{

IIC_PORT&=~SDA;

IIC_PORT&=~SCL;

asm("nop");

IIC_PORT|=SCL;

asm("nop");

IIC_PORT|=SDA;

asm("nop");

}

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

内部函数,等待ACK

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

voidAck_I2C(void)

{

unsignedcharerrtime=20;

IIC_PORT|=SDA;//上拉

IIC_DDR&=~SDA;//设置为输入口

IIC_PORT|=SCL;

asm("nop");

while(PIND&SDA)

{

errtime--;

if(!

errtime)

{

Stop_I2C();

IIC_PORT&=~SDA;//超时,给他个离开的理由

}

}

IIC_PORT&=~SCL;

asm("nop");

IIC_DDR|=SDA;//设置为输出口

}

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

内部函数,I2C发送ACK

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

voidSendAck_I2C()

{

IIC_PORT&=~SDA;//数据线保持拉低,时钟线发生一次从高低的跳变发送一个应答信号

asm("nop");

IIC_PORT|=SCL;

asm("nop");

IIC_PORT&=~SCL;

}

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

内部函数,向总线传送非响应

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

voidSendNotAck_I2C()

{

IIC_PORT|=SDA;//数据线保持高,时钟线发生一次从高低的跳变没有应答

asm("nop");

IIC_PORT|=SCL;

asm("nop");

IIC_PORT&=~SCL;

}

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

内部函数,向总线传送字节

@ch数据

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

voidSend_I2C(intch)

{

inti,a;

for(i=1;i<=8;i++)//发送八位

{

IIC_PORT&=~SCL;//总线放空

delay

(1);

a=(ch&0x80);//根据给定数据,又高位到低位逐步提出字节位,发送到总线上

if(a)

{IIC_PORT|=SDA;}

else

{IIC_PORT&=~SDA;}

ch<<=1;//左循环以便输出下一位

delay

(1);

IIC_PORT|=SCL;//总线使能,发送总线数据

delay

(1);

}

IIC_PORT&=~SCL;//总线8位传送完成,总线放空

}

 

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

内部函数,向总线传送字

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

unsignedintReceive_I2C()

{

unsignedchari,a;

IIC_DDR&=~SDA;//设置为输入口

IIC_PORT|=SDA;//不知道为啥,1的时候读入正确0的时候读入全部为0;

for(i=1;i<=8;i++)//读入八个位

{

a<<=1;//读入数据左循环

IIC_PORT&=~SCL;//总线放空

delay

(1);

IIC_PORT|=SCL;//时钟做一次从低到高的跳变可以接收一位数据

delay

(1);

if(PINF&SDA)////////////////////////此处特别注意,变更SDA引脚时这个一定要跟着变

{a|=1;}

else

{a|=0;}//将数据编入变量a

}

IIC_PORT&=~SCL;//总线放空

IIC_DDR|=SDA;//io变成输出

returna;//反馈接收到的信息

}

 

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

外部函数

向芯片D1307之中地址为address的寄存器写入数据date仅为八位字节

@addtess要写数据的地址

@date要写的数据

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

voidwrite_time(intaddress,intdate)

{

Start_I2C();//启动总线

Send_I2C(0xD0);//呼叫芯片D1307,并定义为写动作

Ack_I2C();//等待响应信号

Send_I2C(address);//发送地址

Ack_I2C();//等待响应信号

Send_I2C(date);//发送数据

Ack_I2C();//等待响应信号

Stop_I2C();//停止总线

}

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

外部函数

从芯片D1307读出10为字节地址1:

秒2:

分3:

时4:

星期5:

号6:

月7:

年8控制字

@addtess要读数据的地址

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

intread_time()

{

inti=0;

Start_I2C();//启动传送

Send_I2C(0xD0);//呼叫芯片D1307,并定义为写动作

Ack_I2C();//等待响应信号

Send_I2C(0x00);//发送起始地址

Ack_I2C();//等待响应信号

Stop_I2C();//关闭总线

Start_I2C();//启动总线

Send_I2C(0xD1);//呼叫芯片D1307,并定义为读动作

Ack_I2C();

for(i=0;i<7;i++)

{aa[i]=Receive_I2C();//接受自初始地址开始的10个字节地址1:

秒2:

分3:

时4:

星期5:

号6:

月7:

年8控制字

if(i<6)SendAck_I2C();//每成功接受一位发送一个响应信号以便接受下一位

if(i==6)SendNotAck_I2C();

}

Stop_I2C();//接受完成停止

}

voidds1307init()

{

write_time(0x00,0x40);

write_time(0x01,0x32);

write_time(0x02,0x10);

write_time(0x03,0x01);

write_time(0x04,0x30);

write_time(0x05,0x10);

write_time(0x06,0x17);

}

//////////以下是LCD12864头文件/////////////////////////////

/*

*========================================================================================================

*

*File:

ws_lcd_st7920.h

*HardwareEnvironment:

*BuildEnvironment:

AVRStudio4.16+Winavr20090313

*Version:

V1.0

*By:

WuZe

*

*(c)Copyright2005-2009,WaveShare

*http:

//www.waveS

*AllRightsReserved

*

*========================================================================================================

*/

#include

#include

#include

#include

#defineLCD_DELAY()_delay_us(75)

unsignedintlcd_buffer[64];

/*

*-------------------------------------------------------------------------------------------------------

*

*从SPI接口发送1byte的数据

*

*-------------------------------------------------------------------------------------------------------

*/

voidspiSendChar(uint8_tsend_char)

{

SPDR=send_char;

while(!

(SPSR&(1<

}

/*

*-------------------------------------------------------------------------------------------------------

*

*给LCD控制芯片ST7920发送指令的函数

*

*-------------------------------------------------------------------------------------------------------

*/

voidsendCodeST7920(uint8_tcode)

{

spiSendChar(0xF8);

spiSendChar(code&0xF0);

spiSendChar((code<<4));

LCD_DELAY();

}

 

/*

*-------------------------------------------------------------------------------------------------------

*

*给LCD控制芯片ST7920发送数据的函数

*

*-------------------------------------------------------------------------------------------------------

*/

voidsendDataST7920(uint8_tdata)

{

spiSendChar(0xFA);

spiSendChar(data&0xF0);

spiSendChar((data<<4));

LCD_DELAY();

}

 

/*

*-------------------------------------------------------------------------------------------------------

*

*读取数据栈内容刷新LCD函数

**lcd_stack指向用于刷新LCD的数据栈,需64byte容量

*

*-------------------------------------------------------------------------------------------------------

*/

voidrefreshLCD(constuint8_t*lcd_stack)

{

uint8_taddr;

sendCodeST7920(0x02);/*地址归位*/

for(addr=0;addr<16;addr++)

{

sendDataST7920(*(lcd_stack+addr));

}

for(addr=32;addr<48;addr++)

{

sendDataST7920(*(lcd_stack+addr));

}

for(addr=16;addr<32;addr++)

{

sendDataST7920(*(lcd_stack+addr));

}

for(addr=48;addr<64;addr++)

{

sendDataST7920(*(lcd_stack+addr));

}

}

 

/*

*-------------------------------------------------------------------------------------------------------

*

*将十进制数据转换成ASCII字符的函数

**str是转换ASCII后存放用的栈

*dec是需要转换的十进制数据

*width是转换成ASCII后的宽度(高位填充'0')

*

*-------------------------------------------------------------------------------------------------------

*/

voiddecToAscii(uint8_t*str,uint16_tdec,uint8_twidth)

{

while(width)

{

switch(width)

{

case5:

{

*str=(dec/10000+'0');

dec%=10000;

break;

}

case4:

{

*str=(dec/1000+'0');

dec%=1000;

break;

}

case3:

{

*str=(dec/100+'0');

dec%=100;

break;

}

case2:

{

*str=(dec/10+'0');

dec%=10;

break;

}

case1:

{

*str=(dec+'0');

break;

}

default:

*str='0';

}

width--;

str++;

}

}

 

/*

*-------------------------------------------------------------------------------------------------------

*

*将十六进制数据转换成ASCII字符的函数

**str是转换ASCII后存放用的栈

*hex是需要转换的十六进制数据

*width是转换成ASCII后的宽度(高位填充'0')

*

*-------------------------------------------------------------------------------------------------------

*/

voidhexToAscii(uint8_t*str,uint16_thex,uint8_twidth)

{

uint16_ttmp;

while(width)

{

switch(width)

{

case4:

{

tmp=(hex>>12);

if(tmp>9)*str=tmp+('A'-10);

else*str=tmp+'0';

break;

}

case3:

{

tmp=(hex>>8)&0x000F;

if(tmp>9)*str=tmp+('A'-10);

else*str=tmp+'0';

break;

}

case2:

{

tmp=(hex>>4)&0x000F;

if(tmp>9)*str=tmp+('A'-10);

else*str=tmp+'0';

break;

}

case1:

{

tmp=hex&0x000F;

if(tmp>9)*str=tmp+('A'-10);

else*str=tmp+'0';

break;

}

default:

*str='0';

}

width--;

str++;

}

}

/*

*-------------------------------------------------------------------------------------------------------

*

*showLine是用于编辑LCD数据栈的函数

*showLine的使用方法与功能类似于ANSIC的printf函数

*例子:

showLine(0,0,lcd_buffer,"Mynameis%c%c.%d3...",'W','s',12);

*上面的例子通过refreshLCD函数刷新后,在带有ST7920控制芯片的LCD上显示的效果为"MynameisWs.012..."

*x对应LCD的横坐标

*y对应LCD的纵坐标

**lcd_stack指向用于刷新LCD的数据栈

**str指向用于将要显示的内容

*

*-------------------------------------------------------------------------------------------------------

*/

voidshowLine(constuint8_tx,constuint8_ty,uint8_t*lcd_stack,char*str,...)

{

uint8_tcoordinate=16*y+x;

va_listmarker;

va_start(marker,str);/*Initializevariablearguments.*/

while(*str!

='\0')

{

if(coordinate>64)break;/*防止堆栈溢出*/

if(*str=='\\')

{

str++;

lcd_stack[coordinate]=*str;

}

elseif(*str=='%')

{

str++;

if(*str=='d'||*str=='D')

{

str++;

decToAscii(&lcd_stack[coordinate],va_arg(marker,uint16_t),(*str-'0'));

coordinate+=(*str-'0'-1);

}

elseif(*str=='c'||*str=='C')

{

lcd_stack[coordinate]=va_arg(marker,uint16_t);

}

elseif(*str=='x'||*str=='X')

{

str++;

hexToAscii(&lcd_stack[coordinate],va_arg(marker,uint16_t),(*str-'0'));

coordinate+=(*str-'0'-1);

}

}

/*如有新的转义符指令请添加在这里*/

else

{

lcd_stack[coordinate]=*str;

}

str++;

coordinate++;

}

va_end(marker);/*Resetvariablearguments.*

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1