⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 《AVR单片机GCC程序设计》
💻 C
字号:
/*
	Mega8 硬件TWI接口读写实时时钟DS1307程序
	文件名:main.c
	
	芯艺 2004-09-02   ---------- 2004-09-07
*/


#include <avr/io.h>
#include <avr/delay.h>
#include <avr/twi.h>
#include <avr/pgmspace.h>

#include <stdio.h>

#define uint unsigned int
#define uchar unsigned char

#define FREQ 4
#define DS1307_ADDR 0XD0

#define TW_ACK  1
#define TW_NACK 0

#define RTC_READ 1
#define RTC_WRITE 0


FILE *g_hFile;

uchar g_aTimeBuf[7];//日历/时钟BCD格式缓冲区
uchar g_aTimeBin[7];//时钟/日历二进制格式缓冲区

void DelayMs(uint ms)
{
	uint i;
	for(i=0;i<ms;i++)
		_delay_loop_2(FREQ *250);
}


/*******************标准I/O功能****************开始********/
//标准I/O输出函数
int usart_putchar(char c)
{
	if(c=='\n')
		usart_putchar('\r');
	loop_until_bit_is_set(UCSRA,UDRE);
	UDR=c;
	return 0;
}
//标准I/O输入函数
int usart_getchar(void)
{
	loop_until_bit_is_set(UCSRA,RXC);
	return UDR;
}

//初始化
void IoInit(void)
{
	DDRC=0;
	PORTC=_BV(PC5)|_BV(PC4);//上拉电阻开
	
	//串行口初始化
	UCSRB=_BV(RXEN)|_BV(TXEN);/*(1<<RXCIE)|(1<<TXCIE)|*/
	UBRRL=25;	//9600 baud 6MHz:38  4MHz:25	
	
	//UART用于标准I/O输入输出
	g_hFile=fdevopen(usart_putchar,usart_getchar,0);	
}
/*******************标准I/O功能**************结束**********/

/*************主模式TWI操作部分*************开始**************/

//总线上起动停止条件
void twi_stop(void)
{
	TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
}
//总线上起动开始条件
uchar twi_start(void)
{
	TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); 
	while ((TWCR & _BV(TWINT)) == 0) ;

	
	return TW_STATUS;
}

//写一字节
uchar twi_writebyte(uchar c)
{
	TWDR = c;
	TWCR = _BV(TWINT) | _BV(TWEN); 	
	while ((TWCR & _BV(TWINT)) == 0);
	return TW_STATUS;
}

//读一字节 ack: true时发ACK,false时发NACK
uchar twi_readbyte(uchar *c ,uchar ack)
{
	uchar tmp=_BV(TWINT)|_BV(TWEN);
		
	if(ack)
		tmp|=_BV(TWEA); 	
	TWCR=tmp;
	while ((TWCR & _BV(TWINT)) == 0) ;

	*c=TWDR;

	return TW_STATUS;
}
/*************主模式TWI操作部分*************结束**************/

/*************DS1307操作**************开始**************/
//对DS1307内存连续的写操作
uchar rtc_write(uchar addr,uchar *buf,uchar len)
{
	uchar i;
	
	twi_start();
	twi_writebyte(DS1307_ADDR|TW_WRITE);
	twi_writebyte(addr);//write address
	for(i=0;i<len;i++)
		twi_writebyte(buf[i]);
	twi_stop();
	return 0;
}

//对DS1307内存连续的读操作
uchar rtc_read(uchar addr,uchar *buf,uchar len)
{
	uchar i;
	
	rtc_write(addr,0,0);//set address
	
	DelayMs(10);
	
	twi_start();
	twi_writebyte(DS1307_ADDR|TW_READ);
	for(i=0;i<len-1;i++)
		twi_readbyte(buf+i,TW_ACK);
	twi_readbyte(buf+i,TW_NACK);

	twi_stop();
	return 0;
}
/*************DS1307操作**************结束**************/

/*************接口部分****************开始**************/

//初始化TWI功能
void RtcInit(void)
{
	TWBR=73;
}

//更新或读取DS1307日历/时间数据
uchar RtcUpdateData(uchar direction)
{
	uchar ret;
	if(direction)	//读
		ret=rtc_read(0,g_aTimeBuf,7);
	else			//写
		ret=rtc_write(0,g_aTimeBuf,7);	

	return ret;
}
//读DS1307用户RAM
uchar RtcReadRAM(uchar addr,uchar *buf,uchar len)
{
	addr+=8;
	return rtc_read(addr,buf,len);
}
//写DS1307用户RAM
uchar RtcWriteRAM(uchar addr,uchar *buf,uchar len)
{
	addr+=8;
	return rtc_write(addr,buf,len);
}

uchar byte_bintobcd(uchar bin)
{
	uchar ret;
	bin&=0x7f;
	bin%=100;
	ret=bin/10;
	ret <<=4;
	ret|=bin%10;
	return ret;
}
uchar byte_bcdtobin(uchar bcd)
{
	uchar ret;
	ret=bcd & 0x0f;
	ret+=(bcd>>4)*10;
	return ret;		
}

//将二进制格式缓冲区(g_aTimeBin)内容转换成BCD格式后保存到BCD格式缓冲区(g_aTimeBuf)
void RtcBinToBCD()
{
	uchar i;
	g_aTimeBin[0]&=0x7f;
	g_aTimeBin[1]&=0x7f;
	g_aTimeBin[2]&=0x3f;
	g_aTimeBin[3]&=0x07;
	g_aTimeBin[4]&=0x3f;
	g_aTimeBin[5]&=0x1f;	
	g_aTimeBin[6]&=0xff;
	
	for(i=0;i<7;i++)
		g_aTimeBuf[i]=byte_bintobcd(g_aTimeBin[i]);
}

//将BCD格式缓冲区(g_aTimeBuf)内容转换成二进制格式后保存到二进制格式缓冲区(g_aTimeBin)
void RtcBCDToBin()
{
	uchar i;
	for(i=0;i<7;i++)
		g_aTimeBin[i]=byte_bcdtobin(g_aTimeBuf[i]);
}

//写DS1307配置字节
void RtcSetSQWOutput(uchar en,uchar level)
{
	//en:方波输出允许 TRUE 有效 level:如果输出禁止 OUT口的逻辑电平
	uchar c=0;
	if(en)	//enable
		c=0x10;
	else	//disable
	{
		if(level)
			c=0x80;
	}
	rtc_write(7,&c,1);
}
/*************接口部分***************结束**************/

int main(void)
{
	uchar i;
	char c;
	int tmp[7];//从标准I/O读取缓冲区
	
	IoInit();
	RtcInit();
	
	printf_P(PSTR("输入命令:g - 打印日历/时钟,s - 设置日历/时钟,h - 帮助信息\n"));	
	
	while(1)
	{
		scanf("%c",&c);
		if(c=='g')
		{
			RtcUpdateData(RTC_READ);
			RtcBCDToBin();
			
			printf_P(PSTR("当前日历/时钟:%d年%d月%d日 星期%d  %d:%d:%d\n"),g_aTimeBin[6],g_aTimeBin[5],g_aTimeBin[4],g_aTimeBin[3],g_aTimeBin[2],g_aTimeBin[1],g_aTimeBin[0]);
		}
		else if(c=='s')
		{
			printf_P(PSTR("请按 < 年 月 日 星期 小时 分 秒 > 格式输入:\n"));
			scanf("%d,%d,%d,%d,%d,%d,%d",tmp+6,tmp+5,tmp+4,tmp+3,tmp+2,tmp+1,tmp);
			
			for(i=0;i<7;i++)
				g_aTimeBin[i]=(uchar)tmp[i];
	
			RtcBinToBCD();
			RtcUpdateData(RTC_WRITE);
			
			printf_P(PSTR("\n设置完成!\n"));
		}
		else if(c=='h')
			printf_P(PSTR("输入命令:g - 打印日历/时钟,s - 设置日历/时钟,h - 帮助信息\n"));	
		else
			continue;
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -