在学习stm8 用它做了个电子钟,一直有问题ds1302 和74hc595 乱码
时间:10-02
整理:3721RD
点击:
#include "stm8s.h"
#include "stm8s_conf.h"
#include "stm8s003f3.h"
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
unsigned char rec_time[3]={0x00,0x12,0x00}; //定义一个数组存储秒,分,时
unsigned char seg[10]={0xFC,0x50,0xCE,0xDA,0X72,0xBA,0xBE,0xD0,0xFE,0xFA};
//定义共阴数码管0~9的段码
unsigned char pos[6]={0x40,0x20,0x10,0x08,0x04,0x02}; //数码管位置信息位码
unsigned char time[6];
void delay_us(unsigned int xx)
{
unsigned int yy = 0;
for(;xx>0;xx--)
{
for(yy = 0;yy<4;yy++)
nop();
}
for(yy = 0;yy<1;yy++)
nop();
nop();
nop();
nop();
nop();
nop();
nop();
}
void delay_ms(int z)
{
int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
/*对DS1320三个管脚和单片机的接口进行字符常量定义*/
/*对74HC595三个管脚和单片机的接口进行字符常量定义*/
//GPIO_WriteLow(GPIOD,GPIO_PIN_2);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_2);//12 STCP
//GPIO_WriteLow(GPIOD,GPIO_PIN_3);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_3);//11脚 移位时钟 SHCP
//GPIO_WriteLow(GPIOD,GPIO_PIN_5);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_5);//14脚 串行数据 DS
void init_595(void)
{
GPIO_DeInit(GPIOD);
GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);
}
/*************************************************
函数名: ds1302_disp_init()
函数功能:初始化连接DS1302、74HC595的端口
入口参数:无
返回值: 无
************************************************/
//GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//CLK HIGH
//GPIO_WriteLow(GPIOC,GPIO_PIN_5);//CLK LOW
//GPIO_WriteHigh(GPIOD,GI80[PIO_PIN_4);//RST HIGH
//GPIO_WriteLow(GPIOD,GPIO_PIN_4);//RST LOW
//GPIO_WriteHigh(GPIOC,GPIO_PIN_4);//IO HIGH
//GPIO_WriteLow(GPIOC,GPIO_PIN_4);//IO LOW
// 初始化DS1302_GPIO
void init_DS1302_GPIO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_CLK
GPIO_Init(GPIOD,GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_RST
GPIO_Init(GPIOC,GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); //RTC_IO
}
void read_IO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT); //RTC_IO
}
void write_IO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_IO
}
/*************************************************
函数名: write_byte( )
函数功能:向DS1302发送一个字节
入口参数:dat--要写入的地址或者数据
返回值: 无
************************************************/
void write_byte(unsigned char dat)
{
unsigned char i;
//write_IO();
// GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
for(i=0;i<8;i++)
{
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
if(dat&0x01)
GPIO_WriteHigh(GPIOC,GPIO_PIN_4);//IO HIGH //判断地址字节的最低位,1位为1则拉高IO
else
{
GPIO_WriteLow(GPIOC,GPIO_PIN_4);
} //1位为0,则输入数据为0,拉低IO
delay_us(1);
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //时钟信号拉高,产生上升沿
//GPIO_WriteLow(GPIOC,GPIO_PIN_5);
delay_us(1);
//GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
dat>>=1; //字节右移一位
}
}
/*************************************************
函数名: read_byte( )
函数功能:从DS1302读出一个字节
入口参数:无
返回值: dat
************************************************/
unsigned char read_byte(void)
{
unsigned char i, dat=0;
read_IO();
// DDA2_bit=0; //设置IO的方向为输入
//IO_L(); //设置IO为高阻态,无上拉电阻
//GPIO_WriteLow(GPIOC,GPIO_PIN_4); //IO low
for(i=0;i<8;i++)
{
dat>>=1; //数据右移一位
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //设置SCLK为高电平
delay_us(1);
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //设置SCLK为低电平,产生下降沿
delay_us(1);
if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_4)==1) //如果读出的数据为1
{
dat|=0x80; //数据位1,则写入1
}
//else dat&=0x7f;
//GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //设置SCLK为高电平
// delay_us(1);
//GPIO_WriteLow(GPIOD,GPIO_PIN_4);
// GPIO_WriteLow(GPIOC,GPIO_PIN_5); //设置SCLK为低电平,产生下降沿
//delay_us(1);
}
write_IO(); //将IO口的方向改为输出
return dat; //返回读取到的数据
}
/*************************************************
函数名: ds1302_write_byte( )
函数功能:向DS1302对应地址发送一个字节
入口参数:add--要写入数据的地址;dat--要写入的数据
返回值: 无
************************************************/
void ds1302_write_byte(unsigned char add,unsigned char dat)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
GPIO_WriteLow(GPIOC,GPIO_PIN_5);//将SCLK拉低
GPIO_WriteHigh(GPIOD,GPIO_PIN_4);//将RST拉高
write_byte(add); //写入地址字节
write_byte(dat); //写入数据
GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//将SCLK拉高
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
}
/*************************************************
函数名: ds1302_read_byte( )
函数功能:从DS1302对应地址读取一个字节
入口参数:add--要读出数据所在的地址
返回值: shuju
************************************************/
unsigned char ds1302_read_byte(unsigned char add)
{
unsigned char shuju; //定义一个变量,存储返回的数据
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //将SCLK拉低
GPIO_WriteHigh(GPIOD,GPIO_PIN_4); //将RST拉高
write_byte(add); //写入地址字节
shuju=read_byte(); //读取该地址字节的数据
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //将SCLK拉高
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
return shuju; //返回读到的数据
}
/*************************************************
函数名: process_dat( )
函数功能:处理单片机读取DS1302得到的时间信息,提取数值
入口参数:无
返回值: 无
************************************************/
void process_dat(void)
{
time[0]=rec_time[0]&0x0f; //提取秒的个位
time[1]=(rec_time[0]&0x70)>>4; //提取秒的十位
time[2]=rec_time[1]&0x0f; //提取分的个位
time[3]=(rec_time[1]&0x70)>>4; //提取分的十位
time[4]=rec_time[2]&0x0f; //提取小时的个位
time[5]=(rec_time[2]&0x30)>>4; //提取小时的十位
}
/*************************************************
函数名: send_595_byte( )
函数功能:单片机向74HC595发送一个字节
入口参数:dat
返回值: 无
************************************************/
void send_595_byte(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_3); //移位时钟拉低
delay_us(5); //延时
//_asm("nop");
// _asm("nop");
if(dat&0x80)
GPIO_WriteHigh(GPIOD,GPIO_PIN_5); //如果提取到的最高位为1,则数据线输出1
else
GPIO_WriteLow(GPIOD,GPIO_PIN_5);
GPIO_WriteHigh(GPIOD,GPIO_PIN_3); //移位时钟拉高,产生上升沿,写入数据
delay_us(5);
//_asm("nop");
// _asm("nop");
dat<<=1; //数据向左移一位
}
}
/*************************************************
函数名: send_595_fram( )
函数功能:单片机向74HC595发送一帧数据(一个数据字节,一个位选字节)
入口参数:dat--数码管显示的数据;position--数码管位置
返回值: 无
************************************************/
void send_595_fram(unsigned char position,unsigned char dat)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_2); //锁存时钟拉低
send_595_byte(position); //串行写入数码管位置信息
send_595_byte(dat); //串行写入数据信息
GPIO_WriteHigh(GPIOD,GPIO_PIN_2); //锁存时钟拉高,产生上升沿,将锁存的数据输出管脚 上
}
/*************************************************
函数名: ds1302_595_display( )
函数功能:将处理完的时间信息显示到数码管上
入口参数:无
返回值: 无
************************************************/
void ds1302_595_display(void)
{
unsigned char j;
for(j=0;j<6;j++)
{
send_595_fram(pos[j],seg[time[j]]); //显示一帧函数
delay_ms(100); //延时2ms
}
}
/*************************************************
函数名: main( )
函数功能:主程序
入口参数:无
返回值: 无
************************************************/
void main()
{
unsigned char i;
unsigned char flag; //设置标志位,存放在RAM的0xc0地址内
init_DS1302_GPIO();
init_595(); //初始化单片机和ds1302及74HC595的接口
delay_ms(1000); //等待初始化完毕
flag=ds1302_read_byte(0xc1); //上电后读取RAM的0xc0地址的字节
// if(flag!=0x01) //判断读出的数据是否是上次写入的值,如果是,就说明ds1302没断电。
//不用初始化时间值,如果不等于0x01,则说明ds1302断电,需要重新初始化时间值。
{
ds1302_write_byte(0x8e,0x00); //解除写保护? 慈胧奔湫畔?
ds1302_write_byte(0xc0,0x01); //向RAM首地址C0H写入数据0x01
ds1302_write_byte(0x80,0x00); //写入秒时间
ds1302_write_byte(0x82,0x50); //写入分时间
ds1302_write_byte(0x84,0x08); //写入时时间
ds1302_write_byte(0x8e,0x80); //使能写保护,以防止误操作写入
}
while(1)
{
for(i=0;i<3;i++)
{
rec_time[i]=ds1302_read_byte(0x81+2*i); //读取ds1302的时间信息,保存到rec_time数组中
}
process_dat(); //调用数据处理函数,对读出的数据进行处理
ds1302_595_display(); //调用数码管显示子程序,显示时间信息
}
}
显示程序一直是乱码,不知道是啥毛病啊,调了老长时间了求大神看看给点建议,谢谢了
#include "stm8s_conf.h"
#include "stm8s003f3.h"
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
unsigned char rec_time[3]={0x00,0x12,0x00}; //定义一个数组存储秒,分,时
unsigned char seg[10]={0xFC,0x50,0xCE,0xDA,0X72,0xBA,0xBE,0xD0,0xFE,0xFA};
//定义共阴数码管0~9的段码
unsigned char pos[6]={0x40,0x20,0x10,0x08,0x04,0x02}; //数码管位置信息位码
unsigned char time[6];
void delay_us(unsigned int xx)
{
unsigned int yy = 0;
for(;xx>0;xx--)
{
for(yy = 0;yy<4;yy++)
nop();
}
for(yy = 0;yy<1;yy++)
nop();
nop();
nop();
nop();
nop();
nop();
nop();
}
void delay_ms(int z)
{
int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
/*对DS1320三个管脚和单片机的接口进行字符常量定义*/
/*对74HC595三个管脚和单片机的接口进行字符常量定义*/
//GPIO_WriteLow(GPIOD,GPIO_PIN_2);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_2);//12 STCP
//GPIO_WriteLow(GPIOD,GPIO_PIN_3);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_3);//11脚 移位时钟 SHCP
//GPIO_WriteLow(GPIOD,GPIO_PIN_5);
//GPIO_WriteHigh(GPIOD,GPIO_PIN_5);//14脚 串行数据 DS
void init_595(void)
{
GPIO_DeInit(GPIOD);
GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);
}
/*************************************************
函数名: ds1302_disp_init()
函数功能:初始化连接DS1302、74HC595的端口
入口参数:无
返回值: 无
************************************************/
//GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//CLK HIGH
//GPIO_WriteLow(GPIOC,GPIO_PIN_5);//CLK LOW
//GPIO_WriteHigh(GPIOD,GI80[PIO_PIN_4);//RST HIGH
//GPIO_WriteLow(GPIOD,GPIO_PIN_4);//RST LOW
//GPIO_WriteHigh(GPIOC,GPIO_PIN_4);//IO HIGH
//GPIO_WriteLow(GPIOC,GPIO_PIN_4);//IO LOW
// 初始化DS1302_GPIO
void init_DS1302_GPIO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_CLK
GPIO_Init(GPIOD,GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_RST
GPIO_Init(GPIOC,GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); //RTC_IO
}
void read_IO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT); //RTC_IO
}
void write_IO(void)
{
GPIO_Init(GPIOC,GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);//RTC_IO
}
/*************************************************
函数名: write_byte( )
函数功能:向DS1302发送一个字节
入口参数:dat--要写入的地址或者数据
返回值: 无
************************************************/
void write_byte(unsigned char dat)
{
unsigned char i;
//write_IO();
// GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
for(i=0;i<8;i++)
{
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
if(dat&0x01)
GPIO_WriteHigh(GPIOC,GPIO_PIN_4);//IO HIGH //判断地址字节的最低位,1位为1则拉高IO
else
{
GPIO_WriteLow(GPIOC,GPIO_PIN_4);
} //1位为0,则输入数据为0,拉低IO
delay_us(1);
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //时钟信号拉高,产生上升沿
//GPIO_WriteLow(GPIOC,GPIO_PIN_5);
delay_us(1);
//GPIO_WriteLow(GPIOC,GPIO_PIN_5); //时钟信号拉低
dat>>=1; //字节右移一位
}
}
/*************************************************
函数名: read_byte( )
函数功能:从DS1302读出一个字节
入口参数:无
返回值: dat
************************************************/
unsigned char read_byte(void)
{
unsigned char i, dat=0;
read_IO();
// DDA2_bit=0; //设置IO的方向为输入
//IO_L(); //设置IO为高阻态,无上拉电阻
//GPIO_WriteLow(GPIOC,GPIO_PIN_4); //IO low
for(i=0;i<8;i++)
{
dat>>=1; //数据右移一位
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //设置SCLK为高电平
delay_us(1);
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //设置SCLK为低电平,产生下降沿
delay_us(1);
if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_4)==1) //如果读出的数据为1
{
dat|=0x80; //数据位1,则写入1
}
//else dat&=0x7f;
//GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //设置SCLK为高电平
// delay_us(1);
//GPIO_WriteLow(GPIOD,GPIO_PIN_4);
// GPIO_WriteLow(GPIOC,GPIO_PIN_5); //设置SCLK为低电平,产生下降沿
//delay_us(1);
}
write_IO(); //将IO口的方向改为输出
return dat; //返回读取到的数据
}
/*************************************************
函数名: ds1302_write_byte( )
函数功能:向DS1302对应地址发送一个字节
入口参数:add--要写入数据的地址;dat--要写入的数据
返回值: 无
************************************************/
void ds1302_write_byte(unsigned char add,unsigned char dat)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
GPIO_WriteLow(GPIOC,GPIO_PIN_5);//将SCLK拉低
GPIO_WriteHigh(GPIOD,GPIO_PIN_4);//将RST拉高
write_byte(add); //写入地址字节
write_byte(dat); //写入数据
GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//将SCLK拉高
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
}
/*************************************************
函数名: ds1302_read_byte( )
函数功能:从DS1302对应地址读取一个字节
入口参数:add--要读出数据所在的地址
返回值: shuju
************************************************/
unsigned char ds1302_read_byte(unsigned char add)
{
unsigned char shuju; //定义一个变量,存储返回的数据
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
GPIO_WriteLow(GPIOC,GPIO_PIN_5); //将SCLK拉低
GPIO_WriteHigh(GPIOD,GPIO_PIN_4); //将RST拉高
write_byte(add); //写入地址字节
shuju=read_byte(); //读取该地址字节的数据
GPIO_WriteHigh(GPIOC,GPIO_PIN_5); //将SCLK拉高
GPIO_WriteLow(GPIOD,GPIO_PIN_4); //将RST拉低
return shuju; //返回读到的数据
}
/*************************************************
函数名: process_dat( )
函数功能:处理单片机读取DS1302得到的时间信息,提取数值
入口参数:无
返回值: 无
************************************************/
void process_dat(void)
{
time[0]=rec_time[0]&0x0f; //提取秒的个位
time[1]=(rec_time[0]&0x70)>>4; //提取秒的十位
time[2]=rec_time[1]&0x0f; //提取分的个位
time[3]=(rec_time[1]&0x70)>>4; //提取分的十位
time[4]=rec_time[2]&0x0f; //提取小时的个位
time[5]=(rec_time[2]&0x30)>>4; //提取小时的十位
}
/*************************************************
函数名: send_595_byte( )
函数功能:单片机向74HC595发送一个字节
入口参数:dat
返回值: 无
************************************************/
void send_595_byte(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_3); //移位时钟拉低
delay_us(5); //延时
//_asm("nop");
// _asm("nop");
if(dat&0x80)
GPIO_WriteHigh(GPIOD,GPIO_PIN_5); //如果提取到的最高位为1,则数据线输出1
else
GPIO_WriteLow(GPIOD,GPIO_PIN_5);
GPIO_WriteHigh(GPIOD,GPIO_PIN_3); //移位时钟拉高,产生上升沿,写入数据
delay_us(5);
//_asm("nop");
// _asm("nop");
dat<<=1; //数据向左移一位
}
}
/*************************************************
函数名: send_595_fram( )
函数功能:单片机向74HC595发送一帧数据(一个数据字节,一个位选字节)
入口参数:dat--数码管显示的数据;position--数码管位置
返回值: 无
************************************************/
void send_595_fram(unsigned char position,unsigned char dat)
{
GPIO_WriteLow(GPIOD,GPIO_PIN_2); //锁存时钟拉低
send_595_byte(position); //串行写入数码管位置信息
send_595_byte(dat); //串行写入数据信息
GPIO_WriteHigh(GPIOD,GPIO_PIN_2); //锁存时钟拉高,产生上升沿,将锁存的数据输出管脚 上
}
/*************************************************
函数名: ds1302_595_display( )
函数功能:将处理完的时间信息显示到数码管上
入口参数:无
返回值: 无
************************************************/
void ds1302_595_display(void)
{
unsigned char j;
for(j=0;j<6;j++)
{
send_595_fram(pos[j],seg[time[j]]); //显示一帧函数
delay_ms(100); //延时2ms
}
}
/*************************************************
函数名: main( )
函数功能:主程序
入口参数:无
返回值: 无
************************************************/
void main()
{
unsigned char i;
unsigned char flag; //设置标志位,存放在RAM的0xc0地址内
init_DS1302_GPIO();
init_595(); //初始化单片机和ds1302及74HC595的接口
delay_ms(1000); //等待初始化完毕
flag=ds1302_read_byte(0xc1); //上电后读取RAM的0xc0地址的字节
// if(flag!=0x01) //判断读出的数据是否是上次写入的值,如果是,就说明ds1302没断电。
//不用初始化时间值,如果不等于0x01,则说明ds1302断电,需要重新初始化时间值。
{
ds1302_write_byte(0x8e,0x00); //解除写保护? 慈胧奔湫畔?
ds1302_write_byte(0xc0,0x01); //向RAM首地址C0H写入数据0x01
ds1302_write_byte(0x80,0x00); //写入秒时间
ds1302_write_byte(0x82,0x50); //写入分时间
ds1302_write_byte(0x84,0x08); //写入时时间
ds1302_write_byte(0x8e,0x80); //使能写保护,以防止误操作写入
}
while(1)
{
for(i=0;i<3;i++)
{
rec_time[i]=ds1302_read_byte(0x81+2*i); //读取ds1302的时间信息,保存到rec_time数组中
}
process_dat(); //调用数据处理函数,对读出的数据进行处理
ds1302_595_display(); //调用数码管显示子程序,显示时间信息
}
}
显示程序一直是乱码,不知道是啥毛病啊,调了老长时间了求大神看看给点建议,谢谢了
谢谢分享的好资料