📄 hjmcu.c
字号:
/**************************************************************************************************
*** 慧净电子1天入门、10天学会、1年精通单片机与C语言视频教程配套程序源码 ***
*** 实验目的:HJ-1G 开发板 AVR配套实验程序 ***
*** MCU: ATmega16 部分C源码可以直接用于项目开发、欢迎复制共享、功德无量、没有版权 ***
*** 作者:慧净免费助学会员
*** 部分源码网上收集整理、如有伤害到你的利益、请来信,hjmcu@163.com 我们的免费助学会员会定期帮你删除掉 ***
*** 编译器:GCC ***
*** 百度交流空间:http://hi.baidu.com/HJMCU WWW.HJMCU.COM ***
*** 论坛交流:http://bbs.hjmcu.com 欢迎来论坛一分钱不要下载配套的仿真电路 ***
*** 配套的硬件学习板网址:http://shop37031453.taobao.com/ ***
*** 日期:2008.8.8 ***
*** 目标:用C语言写程序就这么简单、慧争祝你1天入门、10天学会、1年精通单片机与C语言、找个好工作 ***
***************************************************************************************************/
//慧净电子大学生课程设计专用实验板《HJ-1G》、直接支持AT89S52 STC89C52单片机
//加转接板后支持AVR ATmega16 32 系列单片机、是你学习单片机的得力助手 一板二用,学完51再学AVR
//HJ-1G 学习板加AVR转接板后,装上ATMETAM16 单片机实验
//HJ-1G 学习板AVR单片机实验,FM报警实验
//注意要把JTAGEN 仿真熔丝位设置成1 才能完成本实验,设置成1时不能用仿真口,只能用ISP下载接口下载程序
//本实验要用到电脑串口,可以用串口线接到电脑串口上,也可以用USB转串口线接到电脑USB接口上。
//请用配套的串口调试软件。
//本实验跟据网上的AVR学习笔记有我们的免费助学会员修改成。
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //中断函数头文件
//常量声明
#define BAUD 9600
#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};
//函数声明
void Delayus(unsigned int lus); //us延时函数
void Delayms(unsigned int lms); //ms延时函数
void Port_Init(void); //端口初始化配置
void Usart_Init(void); //USART寄存器设置
void Usart_PutChar(unsigned char cTXData); //字节发送函数
void Usart_PutString(unsigned char *pcString); //字符串发送函数
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初始化
int main(void)
{
unsigned char Set_Time[7] = {0x59,0x59,0x15,0x05,0x12,0x05,0x08};
//设置秒,分,时,日,月,星期,年
unsigned char i;
Port_Init();
Usart_Init();
Usart_PutString("DS1302实时时钟试验");
Usart_PutString("设置当前时间为:");
Usart_PutChar(0x0D);
Usart_PutChar(0x0A); //发送回车换行
Usart_PutChar('2');
Usart_PutChar('0');
Usart_PutChar(Set_Time[6] / 16 + 0x30);
Usart_PutChar(Set_Time[6] % 16 + 0x30);
Usart_PutString("年");
Usart_PutChar(' ');
Usart_PutChar(Set_Time[4] / 16 + 0x30);
Usart_PutChar(Set_Time[4] % 16 + 0x30);
Usart_PutString("月");
Usart_PutChar(' ');
Usart_PutChar(Set_Time[3] / 16 + 0x30);
Usart_PutChar(Set_Time[3] % 16 + 0x30);
Usart_PutString("日");
Usart_PutChar(' ');
Usart_PutChar(Set_Time[2] / 16 + 0x30);
Usart_PutChar(Set_Time[2] % 16 + 0x30);
Usart_PutString("时");
Usart_PutChar(' ');
Usart_PutChar(Set_Time[1] / 16 + 0x30);
Usart_PutChar(Set_Time[1] % 16 + 0x30);
Usart_PutString("分");
Usart_PutChar(' ');
Usart_PutChar(Set_Time[0] / 16 + 0x30);
Usart_PutChar(Set_Time[0] % 16 + 0x30);
Usart_PutString("秒");
Usart_PutChar(' ');
Usart_PutString("星期");
Usart_PutChar(' ');
//Usart_PutChar(Set_Time[5] / 16 + 0x30);
Usart_PutChar(Set_Time[5] % 16 + 0x30);
Usart_PutChar(0x0D);
Usart_PutChar(0x0A); //发送回车换行
DS1302_SetTime(Set_Time);
sei(); //使能全局中断
while(1)
{
DS1302_GetTime();
Usart_PutString("现在时间");
Usart_PutChar(0x0D);
Usart_PutChar(0x0A); //发送回车换行
Usart_PutChar('2');
Usart_PutChar('0');
Usart_PutChar(Get_Time[6] / 16 + 0x30);
Usart_PutChar(Get_Time[6] % 16 + 0x30);
Usart_PutString("年");
Usart_PutChar(' ');
Usart_PutChar(Get_Time[4] / 16 + 0x30);
Usart_PutChar(Get_Time[4] % 16 + 0x30);
Usart_PutString("月");
Usart_PutChar(' ');
Usart_PutChar(Get_Time[3] / 16 + 0x30);
Usart_PutChar(Get_Time[3] % 16 + 0x30);
Usart_PutString("日");
Usart_PutChar(' ');
Usart_PutChar(Get_Time[2] / 16 + 0x30);
Usart_PutChar(Get_Time[2] % 16 + 0x30);
Usart_PutString("时");
Usart_PutChar(' ');
Usart_PutChar(Get_Time[1] / 16 + 0x30);
Usart_PutChar(Get_Time[1] % 16 + 0x30);
Usart_PutString("分");
Usart_PutChar(' ');
Usart_PutChar(Get_Time[0] / 16 + 0x30);
Usart_PutChar(Get_Time[0] % 16 + 0x30);
Usart_PutString("秒");
Usart_PutChar(' ');
Usart_PutString("星期");
Usart_PutChar(' ');
//Usart_PutChar(Set_Time[5] / 16 + 0x30);
Usart_PutChar(Get_Time[5] % 16 + 0x30);
Usart_PutChar(0x0D);
Usart_PutChar(0x0A); //发送回车换行
for(i = 0;i < 4;i++)
{
Delayms(1000);
}
}
}
//端口状态初始化设置函数
void Port_Init()
{
PORTD = 0X00; //USART的发送接收端口分别为PD0和PD1
DDRD |= (1 << PD1); //PD0为接收端口,置为输入口;PD1为发送端口,置为输出口
DDRC |= (1 << PC0) | (1 << PC1); //DS1302的SCLK和I/O引脚设为输出
DDRC |= (1 << PC5); //DS1302的RST引脚设为输出
}
//USART寄存器配置函数
void Usart_Init()
{
UCSRA = 0X00;
UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //异步,数据格式8,N,1
//UCSRC寄存器与UBRRH寄存器共用相同的I/O地址,写 UCSRC 时, URSEL 应设置为 1。
UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率设置
UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //发送使能
}
//字节发送函数
void Usart_PutChar(unsigned char cTXData)
{
while( !(UCSRA & (1 << UDRE)) ); //只有数据寄存器为空时才能发送数据
UDR = cTXData; //发送数据送USART I/O数据寄存器-UDR
}
//接收中断函数
ISR(USART_RXC_vect )
{
unsigned char Rev;
Rev = UDR; //从USART I/O数据寄存器-UDR中读出数据
Usart_PutChar(Rev); //将接收到的数据发送
}
void Usart_PutString(unsigned char *pcString)
{
while (*pcString)
{
Usart_PutChar(*pcString++);
}
}
//从DS1302读一个字节数据
unsigned char DS1302_ReadByte(void)
{
unsigned char i,dat = 0; //dat存放读出的数据,初始化为0
PORTC &= ~(1 << PC0); //DS1302的I/O口上拉不使能,
DDRC &= ~(1 << PC0); //DS1302的I/O口设置为输入口,准备读数据
for(i = 0;i < 8;i++) //读8位,低位在前,右移
{
dat >>= 1; //读出的数据右移一位
PORTC |= (1 << PC1); //DS1302的SCLK端口拉高
Delayus(10); //
PORTC &= ~(1 << PC1); //DS1302的SCLK端口拉低,产生下降沿,
Delayus(10);
if(PINC & (1 << PC0)) //读数据端口状态
{
dat |= 0x80; //如果数据端口位高,相应数据位置1
}
}
DDRC |= (1 << PC0); //最后将数据端口设置为输出
return dat; //返回读出的数据
}
//向DS1302写一个字节数据
void DS1302_WriteByte(unsigned char dat)
{
unsigned char i;
for(i = 0;i < 8;i++) //写8位,低位在前
{
PORTC &= ~(1 << PC1); //DS1302的SCLK置低
if(dat & 0x01) //写数据位
{
PORTC |= (1 << PC0); //如果该位为1,则I/O口置高
}
else
{
PORTC &= ~(1 << PC0); //如果该位为0,则I/O口置低
}
Delayus(10); //
PORTC |= (1 << PC1); //DS1302的SCLK置高,产生上升沿
dat >>= 1; //数据右移1位
}
}
//从DS1302的指定地址读一个字节数据
unsigned char DS1302_ReadData(unsigned addr)
{
unsigned char data;
PORTC &= ~(1 << PC5); //拉低片选端
PORTC &= ~(1 << PC1);//拉低时钟端
Delayus(10);
PORTC |= (1 << PC5);//拉高片选端
Delayus(10);
DS1302_WriteByte(addr);//写入操作命令(地址)
Delayus(10);
data = DS1302_ReadByte();//读出数据
Delayus(10);
PORTC &= ~(1 << PC1); //拉低时钟端
PORTC &= ~(1 << PC5); //拉低片选端
return data;
}
//向DS1302的指定地址写一个字节数据
void DS1302_WriteData(unsigned char addr,unsigned data)
{
PORTC &= ~(1 << PC5); //拉低片选端
PORTC &= ~(1 << PC1);//拉低时钟端
Delayus(10);
PORTC |= (1 << PC5);//拉高片选端
Delayus(10);
DS1302_WriteByte(addr);//写入操作命令(地址)
Delayus(10);
PORTC &= ~(1 << PC1);//拉低时钟端
Delayus(10);
DS1302_WriteByte(data);//写入数据
PORTC &= ~(1 << PC1); //拉低时钟端
Delayus(10);
PORTC &= ~(1 << PC5); //拉低片选端
}
//对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;
/*
//
unsigned char addr;
PORTA &= ~(1 << PA1);
for(i = 0;i < 7;i++)
{
tim[i] = DS1302_ReadData(addr | RD);
addr += 2;
}
*/
////////////////////
PORTC &= ~(1 << PC5);
Delayus(10);
PORTC |= (1 << PC5);
Delayus(10);
DS1302_WriteByte(0xbf);
for(i = 0;i < 8;i++)
{
Get_Time[i] = DS1302_ReadByte();
}
PORTC &= ~(1 << PC5);
///////////////////////////////////
PORTC &= ~(1 << PC1);
}
//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;
}
}
//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(1000); //延时1ms
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -