我在用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);
}
}
|
|