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 pin
uint16_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<
}
key2>>=1;
for(i=0;i<8;i++){
if(0x01<
}
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);
} |