stm32+DS1302+TM1638驱动程序
来源:互联网 发布:网络音响 编辑:程序博客网 时间:2024/06/16 09:35
TM1638数码管显示驱动程序(参考)
1、TM1638与STM32连接
1.1 硬件连接
Vcc--电源+ GND--电源地 STB--PA0 CLK--PA1 DIO--PA2
1.2 驱动程序
TM1638.c文件:
/************************************************************************************************Program Assignment: Driver for TM1638 digital tube**Author : **Date : **Description : This is a driver for the board which is controled by thechip of tm1638. The board has eight digital tubes which have eight segments and eight keys.***********************************************************************************************/ //#include "stm32f10x.h" #include "TM1638.h"/*********************define and global variables*********************************************/#define STB GPIO_Pin_0 //chip-select line#define CLK GPIO_Pin_1 //clock line#define DIO GPIO_Pin_2 //data line#define Set(x) GPIO_SetBits(GPIOA,(x)) //Sets the selected data port bits#define Reset(x) GPIO_ResetBits(GPIOA,(x)) //Resets the selected data port bits#define Get(x) GPIO_ReadInputDataBit(GPIOA,(x))==SET //Read the specified input port pinuint16_t const tm_dat[2][14]={{'0','1','2','3','4','5', //the char and its segment code '6','7','8','9','.','-','_',' '}, {0x3F,0x06,0x5B,0x4F,0x66,0x6D, 0x7D,0x07,0x7F,0x6F,0x80,0x40, 0x08,0x00}};/************************************************************************************************Function Name: RCC_Config *Purpose : Configration Clock***********************************************************************************************/void RCC_Config(){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);}/************************************************************************************************Function Name: GPIO_Config *Purpose : Configration GPIO***********************************************************************************************/void GPIO_Config(){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin=STB|CLK|DIO; GPIO_Init(GPIOA,&GPIO_InitStructure);}/************************************************************************************************Function Name: Write_Byte *Purpose : Write one byte to the data port*params : byte -------8-bits byte *return : none***********************************************************************************************/void Write_Byte(uint8_t byte){ uint8_t i=0; for(i=0;i<8;i++){ Reset(CLK); if(byte&0x01){ Set(DIO); }else{ Reset(DIO); } Set(CLK); byte>>=1; }}/************************************************************************************************Function Name: Read_Byte *Purpose : Read one byte from data port*params : none*return : the 8-bits byte which is read from data port***********************************************************************************************/int8_t Read_Byte(){ uint8_t i=0; uint8_t temp=0x00; for(i=0;i<8;i++){ Set(CLK); temp>>=1; if(Get(DIO)){ temp|=0x80; } Reset(CLK); } return temp;}/************************************************************************************************Function Name: Write_Cmd *Purpose : Write a conmand to the data port*params : cmd -------8-bits byte,the conmand,check the data sheet to find the conmand *return : none***********************************************************************************************/void Write_Cmd(uint8_t cmd){ Set(STB); Reset(STB); Write_Byte(cmd);}/************************************************************************************************Function Name: Read_Key *Purpose : Read the key number which has been pressed*params : none*return : the number of the key. 0-8. "return 0" represents no key has been pressed.***********************************************************************************************/int8_t Read_Key(){ uint8_t i=0; uint8_t key1=0x00; uint16_t key2=0x00; Write_Cmd(0x42); Set(DIO); //this is obligatory, check the data sheet,GPIO for(i=0;i<4;i++){ key1=Read_Byte(); key2|=(key1<<i); } key2>>=1; for(i=0;i<8;i++){ if(0x01<<i==key2)return i+1; } return 0;}/************************************************************************************************Function Name: Write_Dat *Purpose : Write data to the location specified*params : addr ------the address,0x00 to 0x0f dat ------the data,segment code*return : none***********************************************************************************************/void Write_Dat(uint8_t addr,uint8_t dat){ Write_Cmd(0x44); Write_Cmd(0xc0|addr); Write_Byte(dat);}/************************************************************************************************Function Name: TM1638_SendData *Purpose : Write data to the location specified*params : i ------the bit code of digtal tube,0 to 7 str ------the string,the char which was not in tm_data will be replace with "''".*return : none***********************************************************************************************/void TM1638_SendData(uint8_t i,char * str){ int j=0,k=0; unsigned char chr; for(;i<8;i++){ k=0; for(j=0;j<14;j++){ if(*str==tm_dat[0][j]){ chr=tm_dat[1][j]; k=1; break; } } if(k==0){ chr=0x00; } if(*(str+1)=='.'){ chr|=0x80; Write_Dat(i*2,chr); str++; }else{ Write_Dat(i*2,chr); } str++; if(*str=='\0')break; }}/************************************************************************************************Function Name: TM1638_SendIntData *Purpose : Write Int data to the location specified*params : i ------the bit code of digtal tube,0 to 7 num ------the Int.*return : none***********************************************************************************************/void TM1638_SendIntData(uint8_t i,int num){ char a; a = num + '0'; TM1638_SendData(i,&a);}/************************************************************************************************Function Name: TM1638_Init *Purpose : the initialization of tm1638*params : none*return : none***********************************************************************************************/void TM1638_Init(){ int i=0; RCC_Config(); GPIO_Config(); Write_Cmd(0x8a); Write_Cmd(0x40); for(i=0;i<16;i++){ Write_Byte(0x00); }}
TM1638.h
#ifndef __TM1638_H#define __TM1638_H #include "stm32f10x.h"void RCC_Config(void);void GPIO_Config(void);void Write_Byte(uint8_t byte);int8_t Read_Byte(void);void Write_Cmd(uint8_t cmd);int8_t Read_Key(void);void Write_Dat(uint8_t addr,uint8_t dat);void TM1638_SendData(uint8_t i,char * str);void TM1638_SendIntData(uint8_t i,int num);void TM1638_Init(void);#endif
1.3 函数说明
用到的函数:void TM1638_SendData(uint8_t i,char * str);函数说明如下:
/************************************************************************************************Function Name: TM1638_SendData *Purpose : Write data to the location specified*params : i ------the bit code of digtal tube,0 to 7 str ------the string,the char which was not in tm_data will be replace with "''".不显示数据的时候用"''"替换字符*return : none***********************************************************************************************/
int8_t Read_Key(void);函数说明如下:
/************************************************************************************************Function Name: Read_Key *Purpose : Read the key number which has been pressed*params : none*return : the number of the key. 0-8. "return 0" represents no key has been pressed.***********************************************************************************************/
2.DS1302与STM32
2.1硬件连接
Vcc--电源+ GND--电源地 CLK--PC12 DAT--PC11 RST--PC10
2.2驱动程序
DS1302.c的程序网上很多都不能用,查找了硬件时序,发现没问题,但是就是没办法用,下面的程序我亲自测过可以用的,如下:
#include "DS1302.h"//#include "IO.h"#include "delay.h" //*****************DS1302控制命令*******************#define WRITE_SECOND 0x80#define WRITE_MINUTE 0x82#define WRITE_HOUR 0x84#define WRITE_DAY 0x86#define WRITE_MONTH 0x88#define WRITE_WEEK 0x8A#define WRITE_YEAR 0x8C#define WRITE_TIMER_FLAG 0xC0#define READ_SECOND 0x81#define READ_MINUTE 0x83#define READ_HOUR 0x85#define READ_DAY 0x87#define READ_MONTH 0x89#define READ_WEEK 0x8B#define READ_YEAR 0x8D#define READ_TIMER_FLAG 0xC1#define WRITE_PROTECT 0x8E_calendar_obj calendar; //时钟结构体 _next_obj next; //月份数据表 u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表 u8 BCD2HEX(u8 bcd_data) //BCDtoHEX { u8 temp; temp=(bcd_data/16*10 + bcd_data%16); return temp; } u8 HEX2BCD(u8 hex_data) //HEXtoBCD { u8 temp; temp=(hex_data/10*16 + hex_data%10); return temp; } //============================================//函数名称:void Ds1302_Write_Byte (byte addr, byte dat) //功能: 串行发送地址、数据,先发低位,且在上升沿发送//参数传递:有,地址和数据//返回值: 无//=========================================== void IO_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能PA,PB,PC端口时钟 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为50MHz //PC端口初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12; //设置PC10~PC12端口推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(GPIOC, &GPIO_InitStructure); }void Ds1302_Write_Byte(u8 addr, u8 dat) { u8 i; DS1302_IO_OUT(); //数据端口定义为输出 CE = 1; delay_us(10); SCLK = 0; delay_us(10); for(i=0;i<8;i++) { if(addr&0x01) { DIO = 1; } else { DIO = 0; } addr = addr>>1; SCLK = 1; delay_us(10); SCLK = 0; delay_us(10); } for(i=0;i<8;i++) //写入数据:dat { if(dat&0x01) { DIO = 1; } else { DIO = 0; } dat = dat>>1; SCLK = 1; delay_us(10); SCLK = 0; delay_us(10); } CE = 0;; //停止DS1302总线 delay_us(10);}//===============================================//函数名称:byte Ds1302_Read_Byte ( byte addr )//功能: 串行读取数据,先发低位,且在下降沿发送//参数传递:有,地址//返回值: 有,读取的数据//===============================================u8 Ds1302_Read_Byte(u8 addr){ u8 i; u8 temp = 1; CE = 1; delay_us(10); for(i=0;i<8;i++) { SCLK = 0; delay_us(10); if(addr&0x01) { DIO = 1; } else { DIO = 0; } addr = addr>>1; SCLK = 1; delay_us(10); } DS1302_IO_IN(); //数据端口定义为输入 for(i=0;i<8;i++) { temp = temp >> 1; //输出数据:temp SCLK = 0; delay_us(10); if(DIO_IN) { temp |= 0x80; } SCLK = 1; delay_us(10); } DS1302_IO_OUT(); //数据端口定义为输出 SCLK = 0; delay_us(10); CE = 0; //停止DS1302总线 delay_us(10); return temp; }//获得现在是星期几//功能描述:输入公历日期得到星期(只允许1901-2099年)//输入参数:公历年月日 //返回值:星期号 u8 RTC_Get_Week(u16 year,u8 month,u8 day){ u16 temp2; u8 yearH,yearL; yearH=year/100; yearL=year%100; //如果为21世纪,年份数加100 if (yearH>19)yearL+=100; //所过闰年数只算1900年之后的 temp2=yearL+yearL/4; temp2=temp2%7; temp2=temp2+day+table_week[month-1]; if (yearL%4==0&&month<3)temp2--; return(temp2%7);} //===============================================// 向DS1302写入时钟数据//===============================================void RTC_Set(u16 year,u8 mon,u8 day,u8 hour,u8 min,u8 sec) { u8 WR_week; u8 WR_yearL = 0; if(year>=2000) { WR_yearL = year - 2000; } WR_week = RTC_Get_Week(year,mon,day); //根据写入的日期算星期几 Ds1302_Write_Byte(WRITE_PROTECT,0x00); //关闭写保护 Ds1302_Write_Byte(WRITE_SECOND,0x80); //暂停 // Ds1302_Write_Byte(ds1302_charger_add,0xa9); //涓流充电 Ds1302_Write_Byte(WRITE_YEAR,HEX2BCD(WR_yearL)); //年 Ds1302_Write_Byte(WRITE_MONTH,HEX2BCD(mon)); //月 Ds1302_Write_Byte(WRITE_DAY,HEX2BCD(day)); //日 Ds1302_Write_Byte(WRITE_HOUR,HEX2BCD(hour)); //时 Ds1302_Write_Byte(WRITE_MINUTE,HEX2BCD(min)); //分 Ds1302_Write_Byte(WRITE_SECOND,HEX2BCD(sec)); //秒 Ds1302_Write_Byte(WRITE_WEEK,HEX2BCD(WR_week)); //周 Ds1302_Write_Byte(WRITE_PROTECT,0x80); //打开写保护 }//========================================// 从DS1302读出时钟数据//========================================void GetTime(void) { // u8 i,tmp; calendar.w_year = BCD2HEX(Ds1302_Read_Byte(READ_YEAR)); //年 calendar.w_month = BCD2HEX(Ds1302_Read_Byte(READ_MONTH)); //月 calendar.w_date = BCD2HEX(Ds1302_Read_Byte(READ_DAY)); //日 calendar.hour = BCD2HEX(Ds1302_Read_Byte(READ_HOUR)); //时 calendar.min = BCD2HEX(Ds1302_Read_Byte(READ_MINUTE)); //分 calendar.sec = BCD2HEX(Ds1302_Read_Byte(READ_SECOND)&0x7F); //秒 calendar.week = BCD2HEX(Ds1302_Read_Byte(READ_WEEK)); //周 calendar.w_year = calendar.w_year+2000;}//==========================================// DS1302初始化//==========================================void Ds1302_Init(void){ IO_Init(); CE = 0; //RST脚置低 SCLK = 0; //SCK脚置低 Ds1302_Write_Byte(WRITE_SECOND,0x00); //开始 //RTC_Set(2017,4,18,15,23,2) ;}//*******************以下UTC时间计算部分函数*****************//判断是否是闰年函数//月份 1 2 3 4 5 6 7 8 9 10 11 12//闰年 31 29 31 30 31 30 31 31 30 31 30 31//非闰年 31 28 31 30 31 30 31 31 30 31 30 31//输入:年份//输出:该年份是不是闰年.1,是.0,不是u8 Is_Leap_Year(u16 year){ if(year%4==0) //必须能被4整除 { if(year%100==0) { if(year%400==0)return 1; //如果以00结尾,还要能被400整除 else return 0; }else return 1; }else return 0; }
DS1302.h内容如下:
#ifndef __DS1302_H#define __DS1302_H#include "sys.h"#endif//-------------------------------------------------------------------------*//文件名: DS1302.h (实时时钟头文件) *//-------------------------------------------------------------------------*//IO方向设置#define CE PCout(10) // PC10#define DIO PCout(11) // PC11#define SCLK PCout(12) // PC12#define DS1302_IO_IN() {GPIOC->CRH&=0xFFFF0FFF;GPIOC->CRH|=0x00008000;} //低八位引脚的PC11脚定义为输入#define DS1302_IO_OUT() {GPIOC->CRH&=0xFFFF0FFF;GPIOC->CRH|=0x00003000;} //低八位引脚的PC11脚定义为输出//IO操作函数 #define DIO_OUT PCout(11) //数据端口 PC11#define DIO_IN PCin(11) //数据端口 PC11typedef struct { u8 sec; u8 min; u8 hour; u8 day; u8 mon; u16 year; u8 week;}_next_obj; extern _next_obj next;typedef struct { vu8 hour; vu8 min; vu8 sec; //公历日月年周 vu16 w_year; vu8 w_month; vu8 w_date; vu8 week; }_calendar_obj; extern _calendar_obj calendar; //日历结构体extern u32 RTC_sec_sum; //当前时间的总秒值extern u32 Program_sec_sum; //当前编程任务的总秒值,与RTC_sec_sum进行比较void RTC_Set(u16 year,u8 mon,u8 day,u8 hour,u8 min,u8 sec);void GetTime(void);void NEXT_Date(u8 day);u8 RTC_Pro_count(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec,u8 mode);//编程任务时间计算u8 Pro_Get_time(u32 ttt); //编程模式无效时间时计算下次开始的日期void Ds1302_Init(void);
0 0
- stm32+DS1302+TM1638驱动程序
- TM1638八位数码管八按键驱动程序(stm32f103驱动,使用了stm32 3.5库)
- TM1638八位数码管八按键驱动程序(stm32f103驱动,使用了stm32 3.5库)
- DS1302时钟芯片驱动程序
- stm32驱动DS1302芯片
- 51单片机DS1302实时时钟驱动程序
- 51单片机的DS1302的驱动程序
- STM32与DS1302的接口电路
- 基于STM32的DS1302时钟芯片驱动
- ds1302
- DS1302
- DS1302
- Ds1302
- DS1302
- ds1302
- DS1302
- DS1302
- STM32 AD5304驱动程序
- JMS之——ActiveMQ启动时报锁定数据库的问题解决
- 80x86的寻址方式
- Qt Style Sheets(qt样式表)
- 编写C代码makefile模板
- 什么是框架
- stm32+DS1302+TM1638驱动程序
- so共享库
- 2015年第六届蓝桥杯C/C++程序设计本科B组省赛-移动距离
- Windows下编译breakpad (2)
- 14.线程面试题二
- 结束进程的常见方式
- Dubbo框架学习笔记(四)
- CentOS 环境变量编辑、保存、立即生效的方法
- 感知机随机梯度和梯度下降法区别