这是本人曾经做过的一个项目,多多交流!
/*********************************************/
/*程序功能:飞思卡尔加速度传感器MMA7455娱乐仪*/
/*程序模块:1、LED阵列显示模块 */
/* 2、1602显示模块 */
/* 3、I2C通信模块 */
/* 4、按键控制模块 */
/*程序最后修改日期:2010年11月8日星期一 */
/*作者:山西太原瑞生嵌入式 */
/*联系方式:QQ: 253057617 */
/* 旺旺:qq253057617 */
/* E-mail:richgood@163.com */
/*********************************************/
#include <reg52.h>
#include <intrins.h> //要用到_nop_();函数
#define uchar unsigned char
#define uint unsigned int
/***************************************************************************/
/*********** 单片机引脚定义 ************/
/***************************************************************************/
sbit set_key =P3^2; //设置按钮
sbit jia_key =P1^7; //加按钮
sbit jian_key=P1^6; //减按钮
sbit sda=P2^3; //I2C 数据传送位
sbit scl=P2^4; //I2C 时钟传送位
sbit rs=P2^5; //1602RS控制位
sbit rw=P2^6; //1602RW控制位
sbit e =P2^7; //1602E 控制位
/******************************************************************************/
/********** 数据部分 ***********/
/******************************************************************************/
#define IIC_READ 0x1D //定义读指令
#define IIC_WRITE 0x1D //定义写指令
uchar set_key_sign; //是否在设置状态标志
uchar delaysign; //视觉停留标志
uchar xposivalue; //x正方向满格显示g值
uchar xnegavalue; //x反方向满格显示g值
uchar yposivalue; //y正方向满格显示g值
uchar ynegavalue; //y反方向满格显示g值
//11111111 11111110 11111100 --- 10000000 00000000 led_ma:i为亮灯数量
uchar led_ma[9]={0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00};
uchar xposiupstate; //x正方向上8个LED显示状态
uchar xposidownstate; //x正方向下8个LED显示状态
uchar xnegaupstate; //x反方向上8个LED显示状态
uchar xnegadownstate; //x反方向下8个LED显示状态
uchar yupstate; //y方向上8个LED显示状态
uchar ydownstate; //y方向下8个LED显示状态
uchar xposilightnum; //x正方向亮灯数量(1——16)
uchar xnegalightnum; //x反方向亮灯数量(1——16)
uchar yposilightnum; //y正方向亮灯数量(1——8)
uchar ynegalightnum; //x正方向亮灯数量(1——8)
uchar ack_sign; //I2C 应答标志
uchar table1[16]=" hello! X= 0.00"; //1602显示数据
uchar table2[16]=" Y= 0.00 Z= 0.00";
uchar table3[16]="No acceleration!";
uchar table4[10]="0123456789";
uchar table5[8] ="Warning!";
uchar table7[16]="value: X=0.50 ";
/**************************************************************************/
/************ 各延时程序 **************/
/**************************************************************************/
void iic_delay() //5us延时
{
_nop_();
_nop_();
_nop_();
_nop_();
}
void delay() //消除按键抖动
{
unsigned int i;
for(i=0;i<20000;i++);
}
void delay_50us(uint t)
{
uchar j;
for(;t>0;t--)
for(j=19;j>0;j--);
}
void delay_50ms(uchar t)
{
uint j;
for(;t>0;t--)
for(j=6245;j>0;j--);
}
/************************************************************************/
/************** 1602显示部分 *****************/
/************************************************************************/
void write_com(uchar com) //函数功能:写指令
{
e=0;
rs=0;
rw=0;
 0=com;
delay_50us(10);
e=1;
delay_50us(20);
e=0;
}
void write_date(uchar dat) //函数功能:写数据
{
e=0;
rs=1;
rw=0;
 0=dat;
delay_50us(10);
e=1;
delay_50us(20);
e=0;
}
void init1602(void) //函数功能:初始化1602
{
delay_50us(300);
write_com(0x38);
delay_50us(100);
write_com(0x38);
delay_50us(100);
write_com(0x38);
write_com(0x38);
write_com(0x01);
write_com(0x01);
write_com(0x06);
write_com(0x0c);
}
/*********************************************************************/
/************** I2C通信部分 ***************/
/*********************************************************************/
void iic_start() //函数功能:I2C通信开始
{
sda=1;
iic_delay();
scl=1;
iic_delay();
sda=0;
iic_delay();
}
void iic_stop() //函数功能:I2C通信停止
{
sda=0;
iic_delay();
scl=1;
iic_delay();
sda=1;
iic_delay();
}
void iic_ack() //函数功能:I2C通信查应答位
{
sda=1;
scl=1;
iic_delay();
ack_sign=sda;
scl=0;
}
void iic_write_byte(uchar wdata)//函数功能:向I2C从机写入一个字节
{
uchar i,temp,temp1;
temp1=wdata;
for(i=0;i<8;i++)
{
scl = 0;
iic_delay();
temp=temp1;
temp=temp&0x80;
if(temp==0x80)
sda=1;
else
sda=0;
iic_delay();
scl=1;
iic_delay();
scl=0;
iic_delay();
temp1=temp1<<1;
}
}
char iic_read_byte(void) //函数功能:从I2C从机中读出一个字节
{
uchar x;
char data_data;
for(x=0;x<8;x++)
{
data_data=data_data<<1;
sda=1;
iic_delay();
scl=0;
iic_delay();
scl=1;
iic_delay();
if(sda==1)
data_data|=0x01;
//else
// data_data&=0xfe;
}
return data_data;
}
void iic_write(uchar byte_add,uchar wdata)//函数功能:按地址写入一字节数据
{
uchar t;
t=(IIC_WRITE<<1);
iic_start();
iic_write_byte(t);
iic_ack();
iic_write_byte(byte_add);
iic_ack();
iic_write_byte(wdata);
iic_ack();
iic_stop();
}
char iic_read(uchar byte_add) //函数功能:按地址读出一字节数据
{
uchar t;
char x;
t=(IIC_WRITE<<1);
iic_start();
iic_write_byte(t);
iic_ack();
iic_write_byte(byte_add);
iic_ack();
t=((IIC_READ<<1)|0x01);
iic_start();
iic_write_byte(t);
iic_ack();
x=iic_read_byte();
iic_ack();
iic_stop();
return x;
}
/************************************************************************/
/************* LED显示阵列部分 **************/
/************************************************************************/
void led_send(unsigned char t) //函数功能:8051单片机串行通信发送
{
SBUF=t;
while(!TI);
TI=0;
}
void led_show() //函数功能:LED面板显示输出
{
led_send(xnegaupstate);
led_send(xnegadownstate);
led_send(xposiupstate);
led_send(xposidownstate);
led_send(yupstate );
led_send(ydownstate);
}
void led_init() //函数功能:初始化LED面板
{
SCON=0x00;
xposiupstate =led_ma[0];
xposidownstate=led_ma[1];
xnegaupstate =led_ma[0];
xnegadownstate=led_ma[1];
yupstate =led_ma[1];
ydownstate =led_ma[0];
led_show();
}
void led_xposizhi() //函数功能:获取x正方向显示数据
{
if(xposilightnum<8)
{
if(xposilightnum==0)xposilightnum=1;
xposiupstate =led_ma[0];
xposidownstate=led_ma[xposilightnum];
}
else
{
if(xposilightnum>16)xposilightnum=16;
xposiupstate =led_ma[xposilightnum-8];
xposidownstate=led_ma[8];
}
}
void led_xnegazhi() //函数功能:获取x负方向显示数据
{
if(xnegalightnum<8)
{
if(xnegalightnum==0)xnegalightnum=1;
xnegaupstate =led_ma[0];
xnegadownstate=led_ma[xnegalightnum];
}
else
{
if(xnegalightnum>16)xnegalightnum=16;
xnegaupstate =led_ma[xnegalightnum-8];
xnegadownstate=led_ma[8];
}
}
void led_yposizhi() //函数功能:获取y正方向显示数据
{
if(yposilightnum<8)
{
if(yposilightnum==0)yposilightnum=1;
yupstate =led_ma[yposilightnum];
}
else yupstate=led_ma[8];
}
void led_ynegazhi() //函数功能:获取y反方向显示数据
{
switch(ynegalightnum)
{
case 0:ydownstate=0xff;break;
case 1:ydownstate=0x7f;break;
case 2:ydownstate=0x3f;break;
case 3:ydownstate=0x1f;break;
case 4:ydownstate=0x0f;break;
case 5:ydownstate=0x07;break;
case 6:ydownstate=0x03;break;
case 7:ydownstate=0x01;break;
case 8:ydownstate=0x00;break;
default:ydownstate=0x00;break;
}
}
void self_test7455() //函数功能:检测7455有没有插好
{ // 如果没有插好,1602将会显示
uchar j; // “No acceleration!"
char t;
delay_50us(10);
iic_write(0x16,0x05);
delay_50us(20);
t=iic_read(0x16);
if(t!=0x05)
{
write_com(0x80);
for(j=0;j<16;j++)
{
write_date(table3[j]);
delay_50us(10);
}
while(1);
}
else
{
write_com(0x80);
for(j=0;j<16;j++)
{
write_date(table1[j]);
delay_50us(10);
}
write_com(0x80+0x40);
for(j=0;j<16;j++)
{
write_date(table2[j]);
delay_50us(10);
}
}
}
void change_topvalue(uchar x) //函数功能:修改LED面板显示对应的最大g值
{
uchar x1,x2,x3;
x1=(x/100);
x2=(x%100)/10;
x3=(x%100)%10;
write_com(0xcb);
write_date(table4[x1]);
delay_50us(10);
write_com(0xcd);
write_date(table4[x2]);
delay_50us(10);
write_date(table4[x3]);
delay_50us(10);
}
void sendx() //函数功能:向1602发送x轴测量数据
{
uchar x1,x2,x3,xsign;
char x;
x=iic_read(0x06);
if((x&0x80)==0x00)
{
xsign=0x2b; //+
if(x>64)
{
x=(((int)(x*200)/127)-100); //转变为加速度值
x1=(x/100);
x2=(x%100)/10;
x3=(x%100)%10;
delaysign=1;
xposilightnum=x/(xposivalue/16);
}
else
{
x1=0;x2=0;x3=0;
delaysign=0;
}
}
else
{
xsign=0x2d; //-
x=x-0x01;
x=~x;
if(x>64)
{
x=(((int)(x*200)/127)-100);
x1=(x/100);
x2=(x%100)/10;
x3=(x%100)%10;
delaysign=1;
xnegalightnum=x/(xnegavalue/16);
}
else
{
x1=0;x2=0;x3=0;
delaysign=0;
}
}
write_com(0x8B);
write_date(xsign);
delay_50us(10);
write_com(0x8C);
write_date(table4[x1]);
delay_50us(10);
write_com(0x8E);
write_date(table4[x2]);
delay_50us(10);
write_com(0x8F);
write_date(table4[x3]);
delay_50us(20);
}
void sendy() //函数功能:向1602发送y轴测量数据
{
uchar y1,y2,y3,ysign;
char y;
y=iic_read(0x07);
if((y&0x80)==0x00)
{
ysign=0x2b; //+
if(y>66)
{
y=(((int)(y*200)/127)-100); //转变为加速度值
y1=(y/100);
y2=(y%100)/10;
y3=(y%100)%10;
delaysign=1;
yposilightnum=y/(yposivalue/8);
}
else
{
y1=0;y2=0;y3=0;
delaysign=0;
}
}
else
{
ysign=0x2d; //-
y=y-0x01;
y=~y;
if(y>66)
{
y=(((int)(y*200)/127)-100); //转变为加速度值
y1=(y/100);
y2=(y%100)/10;
y3=(y%100)%10;
delaysign=1;
ynegalightnum=y/(ynegavalue/8);
}
else
{
y1=0;y2=0;y3=0;
delaysign=0;
}
}
write_com(0xC3);
write_date(ysign);
delay_50us(10);
write_com(0xC4);
write_date(table4[y1]);
delay_50us(10);
write_com(0xC6);
write_date(table4[y2]);
delay_50us(10);
write_com(0xC7);
write_date(table4[y3]);
delay_50us(20);
}
void sendz() //函数功能:向1602发送z轴测量数据
{
uchar z1,z2,z3,zsign;
char z;
z=iic_read(0x08);
if((z&0x80)==0x00)
{
zsign=0x2b; //+
if(z>68)
{
z=(((int)((z-3)*200)/127)-100); //转变为加速度值
z1=(z/100);
z2=(z%100)/10;
z3=(z%100)%10;
delaysign=1;
}
else
{
z1=0;z2=0;z3=0;
delaysign=0;
}
}
else
{
zsign=0x2d; //-
z=z-0x01;
z=~z;
if(z>62)
{
z=(((int)(z*200)/127)-100); //转变为加速度值
z1=(z/100);
z2=(z%100)/10;
z3=(z%100)%10;
delaysign=1;
}
else
{
z1=0;z2=0;z3=0;
delaysign=0;
}
}
write_com(0xCB);
write_date(zsign);
delay_50us(10);
write_com(0xCC);
write_date(table4[z1]);
delay_50us(10);
write_com(0xCE);
write_date(table4[z2]);
delay_50us(10);
write_com(0xCF);
write_date(table4[z3]);
delay_50us(20);
}
/******************************************************************/
/************** 按键检测部分 **************/
/******************************************************************/
void key_check()
{
uchar i,j;
i=1;
key:if(!set_key)
{
delay();
if(!set_key)
{
set_key_sign=1;
switch(i)
{
case 1:
write_com(0x80);
write_date(0x50);//P
delay_50us(10);
write_date(0x6c);//l
delay_50us(10);
write_date(0x65);//e
delay_50us(10);
write_date(0x61);//a
delay_50us(10);
write_date(0x73);//s
delay_50us(10);
write_date(0x65);//e
delay_50us(10);
write_date(0x20);//空
delay_50us(10);
write_date(0x69);//i
delay_50us(10);
write_date(0x6f);//n
delay_50us(10);
write_date(0x70);//p
delay_50us(10);
write_date(0x75);//u
delay_50us(10);
write_date(0x74);//t
delay_50us(10);
write_date(0x20);//空
delay_50us(10);
write_date(0x58);//X
delay_50us(10);
write_date(0x2b);//+
delay_50us(10);
write_date(0x20);//空
delay_50us(10);
write_com(0xc0);
for(j=0;j<16;j++)
{
write_date(table7[j]);
delay_50us(10);
}
change_topvalue(xposivalue);
i++;
break;
case 2:
write_com(0x8e);
write_date(0x2d); //输出负号
delay_50us(10);
change_topvalue(xnegavalue);
i++;
break;
case 3:
write_com(0x8d);
write_date(0x59); //输出Y
delay_50us(10);
write_date(0x2b); //输出+
delay_50us(10);
write_com(0xc9);
write_date(0x59); //输出Y
delay_50us(10);
change_topvalue(yposivalue);
i++;
break;
case 4:
write_com(0x8e);
write_date(0x2d); //输出负号
change_topvalue(ynegavalue);
i++;
break;
case 5:
i=1;
set_key_sign=0;
write_com(0x80);
for(j=0;j<8;j++)
{
write_date(table5[j]);
delay_50us(10);
}
write_com(0x88);
for(j=8;j<16;j++)
{
write_date(table1[j]);
delay_50us(10);
}
write_com(0xc0);
for(j=0;j<16;j++)
{
write_date(table2[j]);
delay_50us(10);
}
break;
default:break;
}
}
}
if(set_key_sign)
{
if(!jia_key)
{
delay();
if(!jia_key)
{
switch(i-1)
{
case 1:
if(xposivalue!=100)
{
xposivalue++;
change_topvalue(xposivalue);
}
break;
case 2:
if(xnegavalue!=100)
{
xnegavalue++;
change_topvalue(xnegavalue);
}
break;
case 3:
if(yposivalue!=100)
{
yposivalue++;
change_topvalue(yposivalue);
}
break;
case 4:
if(ynegavalue!=100)
{
ynegavalue++;
change_topvalue(ynegavalue);
}
break;
default:break;
}
}
}
if(!jian_key)
{
delay();
if(!jian_key)
{
switch(i-1)
{
case 1:
if(xposivalue!=0)
{
xposivalue--;
change_topvalue(xposivalue);
}
break;
case 2:
if(xnegavalue!=0)
{
xnegavalue--;
change_topvalue(xnegavalue);
}
break;
case 3:
if(yposivalue!=0)
{
yposivalue--;
change_topvalue(yposivalue);
}
break;
case 4:
if(ynegavalue!=0)
{
ynegavalue--;
change_topvalue(ynegavalue);
}
break;
default:break;
}
}
}
}
if(set_key_sign)goto key;
}
/***********************************************************/
/**************** 主函数 ****************/
/***********************************************************/
void data_init()
{
set_key_sign=0;
xposivalue=50;
xnegavalue=50;
yposivalue=50;
ynegavalue=50;
}
void main()
{
uchar j;
led_init();
init1602();
self_test7455();
data_init();
iic_write(0x10,0x32);//校正X值
iic_write(0x12,0x62);//校正Y值
delay_50ms(20);
write_com(0x80);
for(j=0;j<8;j++)
{
write_date(table5[j]);
delay_50us(10);
}
while(1)
{
key_check();
sendx();
if(delaysign)
{
led_xposizhi();
led_xnegazhi();
led_show();
delay_50ms(4);
led_init();
xposilightnum=1;
xnegalightnum=1;
}
sendy();
if(delaysign)
{
led_yposizhi();
led_ynegazhi();
led_show();
delay_50ms(4);
led_init();
ynegalightnum=0;
yposilightnum=1;
}
led_init();
sendz();
if(delaysign)delay_50ms(4);
}
}
/***** 完 .*****/
|