//用OLED屏显示时间,DHT11采集温湿度,并显示
模拟时序,用了BRUST模式和非BRUST模式;两种模式,第一次写博客,还有很多不足的地方,希望各位大神多多指正!有问题请指出来,大家共同学习
#include “DS1302.h”
#include “delay.h”
#include “oled.h”
Timedata ReadTime = {0};
Timedata *pTime;
/*brust模式,秒、分、时、日、月、星期、年
每次写入一个字节,因此写入的数据要与寄存器的的位置相对应,读数据的时候也是对应的
在非brust模式下,在写入数据的时候,首先要写入相应寄存器的地址,之后在相应的地址上写入数据,
在读取数据的时候,在相应的地址上就可以读到相应的数据
*/
uint8_t time_buf[]={0x00,0x25,0x14,0x07,0x07,0x02,0x20};//brust模式
uint8_t time_buf1[]={0x20,0x07,0x07,0x14,0x25,0x00,0x02};//非brust模式
uint8_t val;
void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}
void DS1302_Init(void)
{
GPIO_Config();
DS1302_CS_0;
DS1302_CLK_0;
}
void DS1302_Write_Byte(uint8_t temp)
{
uint8_t i = 0;
DS1302_DAT_Output();//输出
DS1302_CLK_0;
delay_us(2);
for(i=0;i<8;i++)
{
if(temp & 0x01)//低位在前
{
DS1302_DAT_OUT = 1;
delay_us(2);
}
else
{
DS1302_DAT_OUT = 0;
delay_us(2);
}
DS1302_CLK_1;//产生上升沿时钟
delay_us(2);
DS1302_CLK_0;//将时钟拉低,为下次做准备
delay_us(2);
temp = temp>>1;
}
DS1302_DAT_OUT = 1; //释放端口
delay_us(2);
}
void DS1302_Write(uint8_t addr,uint8_t data)
{
DS1302_CS_0;
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_1;
delay_us(2);
addr = addr & 0xfe;//低位为0时是写
DS1302_Write_Byte(addr);
delay_us(2);
DS1302_Write_Byte(data);
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_0;
delay_us(2);
}
uint8_t DS1302_Read_Byte(void)
{
uint8_t i = 0;
uint8_t temp;
DS1302_DAT_Input();//输入
for(i=0;i<8;i++)
{
DS1302_CLK_1;
delay_us(2);
temp >>= 1;
if(DS1302_DAT_IN)
temp = temp | 0x80;
else
temp = temp & 0x7f;
DS1302_CLK_0;
delay_us(2);
}
return temp;
}
uint8_t DS1302_Read(uint8_t addr)
{
DS1302_CS_0;
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_1;
delay_us(2);
addr = addr | 0x01;
DS1302_Write_Byte(addr);
delay_us(2);
val = DS1302_Read_Byte();
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_0;
delay_us(2);
DS1302_DAT_OUT = 0; //释放端口
delay_us(2);
DS1302_DAT_OUT = 1; //释放端口
delay_us(2);
return (val/16*10)+(val%16);//十六进制转换成BCD码
}
/*主要是防止读取的时候,还没读完,数据又变化了,故先将寄存器的数据,
输出到缓冲区内,读取数据时候是去缓冲区进行读取,写也是如此。
指令:
读0xBF
写0xBE
*/
void DS1302_Burst_Write(uint8_t *pdata)
{
uint8_t i = 0;
DS1302_CS_0;
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_1;
delay_us(2);
DS1302_Write_Byte(0xbe);
for(i=0;i<8;i++)
{
DS1302_Write_Byte(pdata[i]);
}
DS1302_CLK_0;
delay_us(2);
DS1302_CS_0;
delay_us(2);
}
void DS1302_Brust_Read(uint8_t *pdat)
{
uint8_t i = 0;
DS1302_CS_0;
delay_us(2);
DS1302_CLK_0;
delay_us(2);
DS1302_CS_1;
delay_us(2);
DS1302_Write_Byte(0xbf);
for(i=0;i<8;i++)
{
pdat[i] = DS1302_Read_Byte();
}
DS1302_CLK_0;
delay_us(2);
DS1302_CS_0;
delay_us(2);
}
void DS1302_Burst_Writetime(void)
{
DS1302_Burst_Write(time_buf);
}
void DS1302_Brust_Readtime(Timedata *ptime)
{
uint8_t pbuf[7];
DS1302_Brust_Read(pbuf);
ptime->year = ((pbuf[6]/16*10)+(pbuf[6]%16));//转换为BCD码
ptime->month = ((pbuf[4]/16*10)+(pbuf[4]%16));
ptime->day = ((pbuf[3]/16*10)+(pbuf[3]%16));
ptime->hour = ((pbuf[2]/16*10)+(pbuf[2]%16));
ptime->minute = ((pbuf[1]/16*10)+(pbuf[1]%16));
ptime->second = ((pbuf[0]/16*10)+(pbuf[0]%16));
ptime->weekday =((pbuf[5]/16*10)+(pbuf[5]%16));
}
void DS1302_Write_Time1(void)
{
DS1302_Write(ds1302_control_add,0x80);//关闭写保护
DS1302_Write(ds1302_sec_add,0x80);//暂停时钟
DS1302_Burst_Writetime();
DS1302_Write(ds1302_control_add,0x80);//打开写保护
}
void DS1302_Write_Time(void)
{
DS1302_Write(ds1302_control_add,0x80);//关闭写保护
DS1302_Write(ds1302_sec_add,0x80);//暂停时钟
DS1302_Write(ds1302_year_add,time_buf1[0]);//写入年
DS1302_Write(ds1302_month_add,time_buf1[1]);//写入月
DS1302_Write(ds1302_date_add,time_buf1[2]);//写入日
DS1302_Write(ds1302_hr_add,time_buf1[3]);//写入时
DS1302_Write(ds1302_min_add,time_buf1[4]);//写入分
DS1302_Write(ds1302_sec_add,time_buf1[5]);//写入秒
DS1302_Write(ds1302_day_add,time_buf1[6]);//写入周
DS1302_Write(ds1302_control_add,0x80);//打开写保护
}
void DS1302_Read_Time(void)
{
ReadTime.year = DS1302_Read(ds1302_year_add);//读取年
ReadTime.month = DS1302_Read(ds1302_month_add);//读取月
ReadTime.day = DS1302_Read(ds1302_date_add);//读取日
ReadTime.hour = DS1302_Read(ds1302_hr_add);//读取时
ReadTime.minute = DS1302_Read(ds1302_min_add);//读取分
ReadTime.second = DS1302_Read(ds1302_sec_add)&0x7f;//读取秒
ReadTime.weekday = DS1302_Read(ds1302_day_add);//读取星期
}
void DS1302_OLED_Display(void)
{
OLED_Refresh();
OLED_ShowNum(0,0,(2000+ReadTime.year),4,16);
OLED_ShowChinese(32,0,31,16);
OLED_ShowNum(48,0,ReadTime.month,2,16);
OLED_ShowChinese(64,0,32,16);
OLED_ShowNum(80,0,ReadTime.day,2,16);
OLED_ShowChinese(96,0,33,16);
OLED_ShowNum(0,16,ReadTime.hour,2,16);
OLED_ShowChar(16,16,':',16);
OLED_ShowNum(24,16,ReadTime.minute,2,16);
OLED_ShowChar(40,16,':',16);
OLED_ShowNum(48,16,ReadTime.second,2,16);
OLED_ShowChinese(64,16,34,16);
OLED_ShowChinese(80,16,35,16);
switch(ReadTime.weekday)
{
case 0x01: OLED_ShowChinese(96,16,36,16);break;
case 0x02: OLED_ShowChinese(96,16,37,16);break;
case 0x03: OLED_ShowChinese(96,16,38,16);break;
case 0x04: OLED_ShowChinese(96,16,39,16);break;
case 0x05: OLED_ShowChinese(96,16,40,16);break;
case 0x06: OLED_ShowChinese(96,16,41,16);break;
case 0x07: OLED_ShowChinese(96,16,42,16);break;
default:break;
}
}
void DS1302_OLED_Display1(void)
{
pTime = &ReadTime;
OLED_Refresh();
OLED_ShowNum(0,0,(2000+pTime->year),4,16);
OLED_ShowChinese(32,0,31,16);
OLED_ShowNum(48,0,pTime->month,2,16);
OLED_ShowChinese(64,0,32,16);
OLED_ShowNum(80,0,pTime->day,2,16);
OLED_ShowChinese(96,0,33,16);
OLED_ShowNum(0,16,pTime->hour,2,16);
OLED_ShowChar(16,16,':',16);
OLED_ShowNum(24,16,pTime->minute,2,16);
OLED_ShowChar(40,16,':',16);
OLED_ShowNum(48,16,pTime->second,2,16);
OLED_ShowChinese(64,16,34,16);
OLED_ShowChinese(80,16,35,16);
switch(pTime->weekday)
{
case 0x01: OLED_ShowChinese(96,16,36,16);break;
case 0x02: OLED_ShowChinese(96,16,37,16);break;
case 0x03: OLED_ShowChinese(96,16,38,16);break;
case 0x04: OLED_ShowChinese(96,16,39,16);break;
case 0x05: OLED_ShowChinese(96,16,40,16);break;
case 0x06: OLED_ShowChinese(96,16,41,16);break;
case 0x07: OLED_ShowChinese(96,16,42,16);break;
default:break;
}
}
#ifndef DS1302_H
#define DS1302_H
#include “stm32f10x.h”
#define DS1302_PORT GPIOE
#define DS1302_IN GPIO_Pin_1 //
#define DS1302_CS GPIO_Pin_2
#define DS1302_CLK GPIO_Pin_3
#define DS1302_CS_1 GPIO_SetBits(DS1302_PORT,DS1302_CS)
#define DS1302_CLK_1 GPIO_SetBits(DS1302_PORT,DS1302_CLK)
#define DS1302_CS_0 GPIO_ResetBits(DS1302_PORT,DS1302_CS)
#define DS1302_CLK_0 GPIO_ResetBits(DS1302_PORT,DS1302_CLK)
#define DS1302_DAT_IN PEin(1)
#define DS1302_DAT_OUT PEout(1)
#define DS1302_DAT_Input() {GPIOE->CRL &= 0XFFFFFF0F;GPIOE->CRL |= (uint32_t)8<<4;} //上拉输入模式
#define DS1302_DAT_Output() {GPIOE->CRL &= 0XFFFFFF0F;GPIOE->CRL |= (uint32_t)3<<4;} //输出,速度是50Mhz
//DS1302地址定义
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //控制数据地址
#define ds1302_charger_add 0x90
#define ds1302_clkburst_add 0xbe
typedef struct
{
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t weekday;
}Timedata;
void GPIO_Config(void);
void DS1302_Init(void);
void DS1302_Write_Byte(uint8_t temp);
void DS1302_Write(uint8_t addr,uint8_t data);
uint8_t DS1302_Read_Byte(void);
uint8_t DS1302_Read(uint8_t addr);
void DS1302_Write_Time(void);
void DS1302_Read_Time(void);
void DS1302_OLED_Display(void);
void DS1302_OLED_Display1(void);
void DS1302_Write_Time1(void);
void DS1302_Brust_Readtime(Timedata *ptime);
void DS1302_Burst_Writetime(void);
void DS1302_Brust_Read(uint8_t *pdat);
void DS1302_Burst_Write(uint8_t *pdata);