[讨论] stm8做了个电子钟,595 和ds1302 一直整不明白求帮忙

y429630084   2013-12-8 13:20 楼主
拿stm8做了个电子钟,595 和ds1302 ,一直整不明白,求看看下。一直显示乱码,谢谢了





#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(unsigned int xx)
{
        unsigned int yy;
        for(;xx > 0;xx--)
        {
        for(yy == 0;yy < 122;yy++)
        {
                delay_us(1);
                nop();
        }

for(yy = 0;yy<2;yy++)
        nop();
}
}

/*对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(1);      //延时2ms
       
  }
}

/*************************************************
函数名:  main( )
函数功能:主程序
入口参数:无
返回值:  无
************************************************/
void main()
{
   unsigned char i;
   unsigned char flag;           //设置标志位,存放在RAM的0xc0地址内
                init_DS1302_GPIO();         
                init_595();                //初始化单片机和ds1302及74HC595的接口
   delay_ms(100);             //等待初始化完毕
   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=ds1302_read_byte(0x81+2*i);    //读取ds1302的时间信息,保存到rec_time数组中
     }
   process_dat();   //调用数据处理函数,对读出的数据进行处理
   ds1302_595_display();        //调用数码管显示子程序,显示时间信息
  }
}

回复评论 (3)

太长了
点赞  2013-12-8 15:14

回复 楼主y429630084 的帖子

看的心都乱了,清晰些……
点赞  2013-12-9 16:31
楼主架构有点乱!其实你没有必要把DS1302的驱动程序也贴出来~~DS1302一直乱码!原因是DS1302驱动程序里面读写操作的延时不准确,导致显示乱码!
点赞  2014-8-29 17:59
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复