打印

ds3232时钟用oled显示

[复制链接]
1564|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yuluabc|  楼主 | 2015-11-17 13:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我在用430f249,oled,ds3232,调试当前时间显示模块,可是读出来的是BCD码,读出来的数据没问题,就是不知道怎么转换才能在oled上显示出来,oled是ssd1305驱动,2.23寸,128*32,大神们帮我看看吧,程序怎么改一下。我的程序如下,数据定义被我删除了。
#include <msp430x24x.h> //声明库

uchar Disp[6]={0};
float Tempreture=0;
void OLED_Port_Initial(void);
void OLED_Write_Comm(uchar comm);

//////////////////////////////////////////////
///////////      延时函数      //////////////
////////////////////////////////////////////                                                   
void Delay_Ms(uint m)
{
uint i,j;
for(i=0;i<m;i++)
   {
    for(j=0;j<121;j++)
       {;}
   }              
}
void Init_IO()
{
    WDTCTL = WDTPW+WDTHOLD;                   //停止看门狗
    P4DIR=0Xff;//设置P4口为输出
    P4OUT=0xff;//P4口置高
    P5DIR=0Xff;//设置P5口为输出
    P5OUT=0xff;//P5口置高   
    P6DIR=0Xff;//设置P6口为输出
    P6OUT=0xff;//P6口置高     
}
void delay_us(uint x)
{
x=x*1;
while(--x);
}
void start()  //开始信号
{        
SET_SDA;
delay_us(2);
SET_SCL;
delay_us(2);
CLR_SDA;
delay_us(2);
delay_us(2);
}
void stop()   //停止
{
CLR_SDA;
delay_us(2);
SET_SCL;
delay_us(2);
SET_SDA;
delay_us(2);
}
void respons()  //应答
{
uint j=0;
P6DIR=0Xfd; //设置P6.1为输入口
P6REN|=0x02;//允许P6.1口上下拉功能
P6OUT|=0x02;//P6.1为上拉
SET_SCL;
delay_us(2);
while((SDA_DATA_val)&&(j<250))//
     {
      j++;
    }
P6DIR=0Xff;//设置P1口为输出,也就是把P1.4功能从输入换为输出
CLR_SCL;
delay_us(2);
}
void Ack_I2c()// 回应ACK
{
CLR_SDA;
delay_us(2);
SET_SCL;   
delay_us(2);                    /*清时钟线,钳住I2C总线以便继续接收*/
CLR_SCL;  
delay_us(2);
}
void NO_Ack_I2c()//非应答
{
SET_SDA;
delay_us(2);
SET_SCL;   
delay_us(2);
CLR_SCL;  
delay_us(2);
}
void write_byte(uchar date)//写一字节数据
{
uchar i=0,temp;
temp=date;
for(i=0;i<8;i++)
        {
         CLR_SCL;
         delay_us(2);
     if(temp&0x80)//如果最高位为1则拉高数据线,否则拉低数据线
        SET_SDA;
     else
        CLR_SDA;
     temp=temp<<1;
     delay_us(2);
     SET_SCL;
     delay_us(2);
     CLR_SCL;
     delay_us(2);
    }
CLR_SCL;
delay_us(2);
SET_SDA;
delay_us(2);
}
uchar read_byte()//对一字节数
{
uchar i,k=0;
CLR_SCL;
delay_us(2);
SET_SDA;
P6DIR=0Xfd;
P6REN=0x02;
P6OUT=0x02;
delay_us(2);
for(i=0;i<8;i++)
        {   
     SET_SCL;
     delay_us(20);        
     k*=2;     
     if(SDA_DATA_val)
        k=k+1;
     CLR_SCL;
     delay_us(2);        
        }
P6DIR=0Xff;
return k;
}
uint MLX90614_Read(uchar command)//读出温度数据
{
uchar d0,d1;
uchar ddd;
start();
write_byte(SLAVE_ADDR_WR);
respons();
write_byte(command);
respons();
start();
write_byte(SLAVE_ADDR_RD);
respons();
d0=read_byte();
Ack_I2c();
d1=read_byte();
Ack_I2c();
ddd=read_byte();
NO_Ack_I2c();
stop();
return (d1<<8|d0);
}

/************DS3231********************/
void delay_us_DS3231(uint x)
{
x=x*1;
while(--x);
}
void start_DS3231()  //开始信号
{        
SET_SDA_DS3231;
delay_us_DS3231(2);
SET_SCL_DS3231;
delay_us_DS3231(2);
CLR_SDA_DS3231;
delay_us_DS3231(2);
delay_us_DS3231(2);
}
void stop_DS3231()   //停止
{
CLR_SDA_DS3231;
delay_us_DS3231(2);
SET_SCL_DS3231;
delay_us_DS3231(2);
SET_SDA_DS3231;
delay_us_DS3231(2);
}
void respons_DS3231()  //应答
{
uint j=0;
P6DIR=0X7f; //设置P6.7为输入口
P6REN|=0x80;//允许P6.7口上下拉功能
P6OUT|=0x80;//P6.1为上拉
SET_SCL_DS3231;
delay_us_DS3231(2);
while((SDA_DATA_val_DS3231)&&(j<250))//
     {
      j++;
    }
P6DIR=0Xff;//设置P1口为输出,也就是把P1.4功能从输入换为输出
CLR_SCL_DS3231;
delay_us_DS3231(2);
}
void Ack_I2c_DS3231()// 回应ACK
{
CLR_SDA_DS3231;
delay_us_DS3231(2);
SET_SCL_DS3231;   
delay_us_DS3231(2);                    /*清时钟线,钳住I2C总线以便继续接收*/
CLR_SCL_DS3231;  
delay_us_DS3231(2);
}
void NO_Ack_I2c_DS3231()//非应答
{
SET_SDA_DS3231;
delay_us_DS3231(2);
SET_SCL_DS3231;   
delay_us_DS3231(2);
CLR_SCL_DS3231;  
delay_us_DS3231(2);
}
void write_byte_DS3231(uchar date)//写一字节数据
{
uchar i=0,temp;
temp=date;
for(i=0;i<8;i++)
        {
         CLR_SCL_DS3231;
         delay_us_DS3231(2);
     if(temp&0x80)//如果最高位为1则拉高数据线,否则拉低数据线
        SET_SDA_DS3231;
     else
        CLR_SDA_DS3231;
     temp=temp<<1;
     delay_us(2);
     SET_SCL_DS3231;
     delay_us(2);
     CLR_SCL_DS3231;
     delay_us(2);
    }
CLR_SCL_DS3231;
delay_us_DS3231(2);
SET_SDA_DS3231;
delay_us_DS3231(2);
}
uchar read_byte_DS3231()//对一字节数
{
uchar i,k=0;
CLR_SCL_DS3231;
delay_us_DS3231(2);
SET_SDA_DS3231;
P6DIR=0X7f;
P6REN=0x80;
P6OUT=0x80;
delay_us_DS3231(2);
for(i=0;i<8;i++)
        {   
     SET_SCL_DS3231;
     delay_us_DS3231(20);        
     k*=2;     
     if(SDA_DATA_val_DS3231)
        k=k+1;
     CLR_SCL_DS3231;
     delay_us_DS3231(2);        
        }
P6DIR=0Xff;
return k;
}


uchar BCD2HEX(uchar val)    //BCD转换为Byte
{
    uchar temp;
    temp=val&0x0f;
    val>>=4;
    val&=0x0f;
    val*=10;
    temp+=val;
   
    return temp;
}

uchar HEX2BCD(uchar val)    //B码转换为BCD码
{
    uchar i,j,k;
    i=val/10;
    j=val;
    k=j+(i<<4);
    return k;
}
uint Read_DS3231(uchar command)//读出温度数据
{
uchar d0,d1;
uchar ddd_DS3231;
start_DS3231();
write_byte_DS3231(SLAVE_ADDR_WR_DS3231);
respons_DS3231();
write_byte_DS3231(command);
respons_DS3231();
start_DS3231();
write_byte_DS3231(SLAVE_ADDR_RD_DS3231);
respons_DS3231();
d0=read_byte_DS3231();
Ack_I2c_DS3231();
d1=read_byte_DS3231();
Ack_I2c_DS3231();
ddd_DS3231=read_byte_DS3231();
NO_Ack_I2c_DS3231();
stop_DS3231();
return (d1<<8|d0);
}

void Single_Write(unsigned char address, unsigned char thedata)
{
    start_DS3231();//启动
    write_byte_DS3231(SLAVE_ADDR_WR_DS3231);        //写入设备ID及写信号
    write_byte_DS3231(address);        //X地址
    write_byte_DS3231(thedata);        //写入设备ID及读信
    stop_DS3231();
}

void DS3231_Init()
{
   Single_Write(DS3231_CONTROL, 0x1C);
   Single_Write(DS3231_STATUS, 0x00);
}
void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec)
{
    uchar temp=0;
    temp=HEX2BCD(yea);
    Single_Write(DS3231_YEAR,temp);   //修改年
   
    temp=HEX2BCD(mon);
    Single_Write(DS3231_MONTH,temp);  //修改月
   
    temp=HEX2BCD(da);
    Single_Write(DS3231_DAY,temp);    //修改日
   
    temp=HEX2BCD(hou);
    Single_Write(DS3231_HOUR,temp);   //修改时
   
    temp=HEX2BCD(min);
    Single_Write(DS3231_MINUTE,temp); //修改分
   
    temp=HEX2BCD(sec);
    Single_Write(DS3231_SECOND,temp); //修改秒
}

void OLED_Init()
{
        OLED_Port_Initial();
        OLED_Write_Comm(0xAE);
        OLED_Write_Comm(0x02);
        OLED_Write_Comm(0x10);
        OLED_Write_Comm(0x40);    /*set display start line*
        OLED_Write_Comm(0xB0);    /*set page address*/
        OLED_Write_Comm(0x81);    /*contract control*/
        OLED_Write_Comm(0x80);    /*128*/
        
        OLED_Write_Comm(0xA1);    /*set segment remap*/
        OLED_Write_Comm(0xA4);    /*normal display*/
        OLED_Write_Comm(0xA6);    /*normal / reverse*/
        
        OLED_Write_Comm(0xA8);    /*multiplex ratio*/
        OLED_Write_Comm(0x1F);    /*duty = 1/32*/
        OLED_Write_Comm(0xC8);    /*Com scan direction*/
        OLED_Write_Comm(0xD3);    /*set display offset*/
        OLED_Write_Comm(0x00);
        
        OLED_Write_Comm(0xD5);    /*set osc division*/
        OLED_Write_Comm(0x00);
        
        OLED_Write_Comm(0xD8);    /*set area color mode off*/
        OLED_Write_Comm(0x00);
        
        OLED_Write_Comm(0xD9);    /*set pre-charge period*/
        OLED_Write_Comm(0x01);
        
        OLED_Write_Comm(0xDA);    /*set COM pins*/
        OLED_Write_Comm(0x12);     
        OLED_Write_Comm(0xAF);    /*display ON*/

}
void OLED_Port_Initial(void)
{       OLED_RES_LOW;
        OLED_CS_OFF;
        OLED_DC_COMM;
        OLED_SCLK_HIGH;
        OLED_SDIN_HIGH;
        Delay_Ms(200);
        OLED_RES_HIGH;
        Delay_Ms(200);
}
//向写OLED模块写命令函数:把命令写入OLED命令寄存器,高位在前
void OLED_Write_Comm(uchar comm)
{
        uchar i;
        OLED_DC_COMM;                                                //命令模式
        OLED_CS_ON;                                                        //开启片选
        for(i=0;i<8;i++)
        {
                OLED_SCLK_LOW;                        //制造SCLK上升沿
                  if(0x80==(comm&0x80))                                //把最高位状态赋给SDIN
                        OLED_SDIN_HIGH;
                else
                          OLED_SDIN_LOW;                        
                OLED_SCLK_HIGH;
                comm<<=1;                                                //命令向左移一位
        }
        OLED_CS_OFF;                                //关闭片选
}
void OLED_Write_Data(uchar data)
{
        uchar i;
        OLED_DC_DATA;                                //数据模式
        OLED_CS_ON;                                //开启片选
        for(i=0;i<8;i++)
        {
            OLED_SCLK_LOW;                        //制造SCLK上升沿
                if(0x80==(data&0x80))                        //把最高位状态赋给SDIN
                        OLED_SDIN_HIGH;
                else
                          OLED_SDIN_LOW;                                
                OLED_SCLK_HIGH;
                data<<=1;                                                //命令向左移一位
        }
        OLED_CS_OFF;                                //关闭片选
}
//开启OLED显示   
void OLED_Display_On(void)
{
        OLED_Write_Comm(0X8D);  //SET DCDC命令
        OLED_Write_Comm(0X14);  //DCDC ON
        OLED_Write_Comm(0XAF);  //DISPLAY ON
}  
void OLED_Display_Off(void)
{
        OLED_Write_Comm(0X8D);  //SET DCDC命令
        OLED_Write_Comm(0X10);  //DCDC OFF
        OLED_Write_Comm(0XAE);  //DISPLAY OFF
    //OLED_SDIN_HIGH;
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!         
void OLED_Clear(void)  
{  
        uchar i,n;  
        for(i=0;i<4;i++)
        {
                OLED_Write_Comm(0xb0+i);    //设置页地址(0~7)
                OLED_Write_Comm(0x00);      //设置显示位置—列低地址
                OLED_Write_Comm(0x10);      //设置显示位置—列高地址
                for(n=0;n<132;n++)
                        OLED_Write_Data(0x00);
        }   
}
//满屏函数,屏幕全亮
void OLED_Full(void)
{
        uchar i,n;  
        for(i=0;i<4;i++)
        {
                OLED_Write_Comm(0xb0+i);    //设置页地址(0~7)
                OLED_Write_Comm(0x00);      //设置显示位置—列低地址
                OLED_Write_Comm(0x10);      //设置显示位置—列高地址
                for(n=0;n<128;n++)
                        OLED_Write_Data(0xff);
        }
}
void OLED_ShowChar(uchar startpage,uchar startcolumn,const uchar *dis_code,uchar len ,uchar width,uchar mode)
{                                 
        uchar x_temp = 0;
        uchar y_temp = 0;
        uchar page_sum= 0;
        uint i_temp =0;
        uchar col_l = 0;
        uchar col_h = 0;
        col_l=LO_UINT8(startcolumn);
        col_h=HI_UINT8(startcolumn);
        if(width<=8)
        {
                page_sum =1;
        }
        else if((width>8) && (width<=16))
                {
                        page_sum =2;
                }
        else if((width>16) && (width<=24))
                {
                        page_sum =3;
                }
        else if((width>24) && (width<=32))
                {
                        page_sum =4;
                }
        else
                {
                        return;
                }
        for(y_temp=startpage;y_temp<page_sum+startpage;y_temp++)
        {                                
                OLED_Write_Comm(col_l+0x00);      /*set lower column address*/
                OLED_Write_Comm(col_h+0x10);      /*set higher column address*/
                if(y_temp <4)
                        OLED_Write_Comm(0xB0+y_temp);    /*set page address*/               
                else//防止溢出
                        OLED_Write_Comm(0xB0+y_temp-4);
                for(x_temp = startcolumn; x_temp<(len+startcolumn); x_temp++)
                {
                        if(1==mode)
                                OLED_Write_Data(dis_code[i_temp++]);
                        else
                                OLED_Write_Data(~(dis_code[i_temp++]));
                }                                          
        }
}

void LCD_Set_Pos(byte x, byte y)
{
  OLED_Write_Comm(0xb0+y);
  OLED_Write_Comm(((x&0xf0)>>4)|0x10);
  OLED_Write_Comm((x&0x0f)|0x01);
}

//==============================================================
//功能描述:写入一组标准ASCII字符
//参数:显示的位置(x,y),y为页范围0~7,要显示的字符串
//返回:无
//==============================================================
void write_6_8_char(byte x,byte y,byte ucData)
{
    byte i, ucDataTmp;      
    ucDataTmp = ucData-32;
    if(x > 126)
    {
        x= 0;
        y++;
    }
   
    LCD_Set_Pos(x, y);
   
    for(i = 0; i < 6; i++)
    {     
        OLED_Write_Data(F6x8[ucDataTmp][i]);  
    }
}

void write_6_8_string(byte x,byte y,byte ch[])
{
  byte c=0,i=0,j=0;      
  while (ch[j]!='\0')
  {   
    c =ch[j]-32;
    if(x>126){x=0;y++;}
    LCD_Set_Pos(x,y);   
          for(i=0;i<6;i++)     
            OLED_Write_Data(F6x8[c][i]);  
          x+=6;
          j++;
  }
}
void write_6_8_number(unsigned char x,unsigned char y, float number)
{
  unsigned char i=0;
  unsigned char temp[16];
  unsigned char *point=temp;
  float decimal;
  int data;
  
  if(number<0)
    {
     temp[0]='-';
     write_6_8_char(x,y,temp[0]);
     x+=6;
     number=-number;
    }
   
  data=(int)number;
  decimal=number-data;     //得到小数部
  if(data>=1000)           //是否可被1000整除
    {
     temp[i]=48+data/1000;
     data=data%1000;
     i++;
    }

   
  if(data>=100)              //是否可被100整除
   {
    temp[i]=48+data/100;
    data=data%100;
    i++;
   }
  else
    if(data<100&&i!=0)
     {
     temp[i]=0+48;
     i++;
     }
   
  if(data>=10)                  //是否可被10整除
    {
     temp[i]=48+data/10;
     data=data%10;
     i++;
    }
  else
    if(data<10&&i!=0)
     {
     temp[i]=48;
     i++;
     }
     
  temp[i]=48+data;
   
      
  if(decimal>=0.0001)           //判断是否为小数
   {
    i++;
    temp[i]='.';                //加小数点
    i++;
   
    data=(int)(decimal*1000);
   
    temp[i]=48+data/100;
   
    data=data%100;
    i++;
   
    if(data>0)
      {
       temp[i]=48+data/10;
       data=data%10;
      
      
      }
    if(data>=0)
      {
       i++;
       temp[i]=data+48;
      }
   
   }     

  i++;
  temp[i]='\0';
    write_6_8_string(x,y,point);
  
}

//在指定的位置显示字符串,字符大小:16*8(字符)、16*16(汉字)
void OLED_Show_String16(uchar startpage,uchar startcolumn,uchar *pdata,uchar mode)
{
        uchar adata[3];
        uchar currentcolumn=startcolumn;        
        while(*pdata)
        {
                adata[0]=*pdata;
                if(((*pdata) < 0x80) && ((*pdata) >= 0x20))                //ASCI码为字符
                {
                        OLED_ShowChar(startpage,currentcolumn,(uchar *)&Ascii_8x16[(*pdata-0x20)][0],8,16,mode);
                        currentcolumn+=8;
                }
                if(((*pdata) >= 0x80) && ((*pdata) <= 0xFE))        //如果为汉字
                {
                        uchar tmp = 0;
                    uchar i = 0;
                    uchar readData;
                          adata[1]= *(pdata + 1);
                        while(1)
                        {
                                readData = (GB16[i].Index[0]);
                                if(0 == readData)
                                        break;
                                if(adata[0] == readData)
                                {
                                        readData =(GB16[i].Index[1]);
                                        if(adata[1] == readData)
                                        {
                                                tmp = i;
                                                break;
                                        }
                                }
                                i++;
                        }
                        OLED_ShowChar(startpage,currentcolumn,(uchar *)&GB16[tmp].Msk[0],16,16,mode);
                        currentcolumn+=16;
                        pdata++;
                }
                pdata++;
        }
}
unsigned int year=2015,month=11,date=16,week=1,hour=13,min=48,second=20;
void main(void)//主函数
{
  //uint Din=0;
  uchar i=0;
    Init_IO();//初始化IO口
    /*------选择系统主时钟为8MHz-------*/
    BCSCTL1 &= ~XT2OFF;                 //打开XT2高频晶体振荡器
    do
    {
        IFG1 &= ~OFIFG;                 //清除晶振失败标志
        for (i = 0xFF; i > 0; i--);     //等待8MHz晶体起振
    }
    while ((IFG1 & OFIFG));             //晶振失效标志仍然存在?
    BCSCTL2 |= SELM_2 + SELS;           //MCLK和SMCLK选择高频晶振  
    OLED_Init();                                //OLED模块初始化
    OLED_Clear();
    OLED_Display_On();
    DS3231_Init();//初始化
    ModifyTime(15,11,16,16,48,01);//初始化时钟,2015/11/16,16/48/01
    while(1)//无限循环
         {           
          Tempreture=MLX90614_Read(0x07);//读地址7的温度数据即物体温度      
          Tempreture=Tempreture*0.02-273.15; // 温度换算

         year=BCD2HEX(Read_DS3231(DS3231_YEAR));//年
         month=BCD2HEX(Read_DS3231(DS3231_MONTH));//月
         date=BCD2HEX(Read_DS3231(DS3231_DAY));//日
         hour=BCD2HEX(Read_DS3231(DS3231_HOUR));//时
         
         min=BCD2HEX(Read_DS3231(DS3231_MINUTE));//分
         second=BCD2HEX(Read_DS3231(DS3231_SECOND));//秒
         week=BCD2HEX(Read_DS3231(DS3231_WEEK));//星期
         
          write_6_8_string(10,0,"temp:");
          write_6_8_number(65,0,Tempreture);
         
          write_6_8_string(10,1,"year");
          write_6_8_string(50,1,"mon");
          write_6_8_string(85,1,"day");
         
          write_6_8_number(10,2,2015);
          write_6_8_number(50,2,11);
          write_6_8_number(85,2,16);
                    
          write_6_8_string(0,3,"wk");
          write_6_8_number(30,3,1);
         
          //write_6_8_string(35,4,"hour");
          write_6_8_number(75,3,22);
         
          //write_6_8_string(10,5,"min");
          write_6_8_number(90,3,10);
         
          //write_6_8_string(10,6,"second");
         // write_6_8_number(100,3,second);

          Delay_Ms(100);
         }
}

相关帖子

沙发
dirtwillfly| | 2015-11-18 08:43 | 只看该作者
那么长的代码,基本没人会读的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

49

帖子

0

粉丝