|
花费了4、5天时间终于彻底搞好了数字指南针模块的TWI和UART程序,这是TWI程序,其中参考了双龙的资料,LCD使用了网站上的1602LCD的程序,目前的功能是:通电后MEGA16不断的读取数字指南针的高、低位数据,并在LCD上显示出来:如:指向正北时显示 North 000 正东时显示 East 090等;
将PC7接地开始硬件补偿,这时把数字指南针旋转一圈以上,然后将PC6接地结束硬件补偿;将PC5接地将进行正北校正!以下是源程序:
#include<iom16v.h>
#include<macros.h>
#include<stdio.h>
#include"TWI.H"
#define rd_device_add 0x77
#define wr_device_add 0x76
#define uchar unsigned char
#define LCD_EN_PORT PORTD
#define LCD_RW_PORT PORTD
#define LCD_RS_PORT PORTD
#define LCD_DATA_PORT PORTA
#define LCD_DATA_DDR DDRA
#define LCD_DATA_PIN PINA
#define LCD_EN 0x80 //portd7 out
#define LCD_RS 0x40 //portd6 out
#define LCD_DATA 0xf0 //porta4/5/6/7 out
extern void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s);
unsigned char bb[]="000";
unsigned char b,c,d;
unsigned int a;
void LCD_init(void)
{ unsigned char i;
delay_nms(1000);
i=0;
for (i=0;i<20;i++)
{
LCD_write_char(0x28,0); //4bit test
delay_nms(15);
}
LCD_write_char(0x0c,0);
delay_nms(5);
LCD_write_char(0x01,0);
}
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_set_xy( X, Y );
while (*s)
{
LCD_write_char( 0, *s );
s ++;
}
}
void LCD_write_word(unsigned char X,unsigned char Y,unsigned char n)
{
LCD_set_xy( X, Y );
LCD_write_char( 0, n );
}
void LCD_set_xy( unsigned char x, unsigned char y )
{
unsigned char address;
if (y == 0) address = 0x80 + x;
else
address = 0xc0 + x;
LCD_write_char( address, 0 );
}
void LCD_en_write(void)
{
LCD_EN_PORT|=LCD_EN;
delay_nus(1);
LCD_EN_PORT&=~LCD_EN;
}
void LCD_write_char(unsigned command,unsigned data)
{
unsigned command_temp,data_temp;
command_temp=command;
data_temp=data;
delay_nus(16);
if(command==0)
{
LCD_RS_PORT|=LCD_RS; //RS=1
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=data_temp&0xf0;
LCD_en_write();
data_temp=data_temp<<4;
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=data_temp&0xf0;
LCD_en_write();
}
else
{
LCD_RS_PORT&=~LCD_RS; //RS=0
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=command_temp&0xf0;
LCD_en_write();
command_temp=command_temp<<4;
LCD_DATA_PORT&=0x0f;
LCD_DATA_PORT|=command_temp&0xf0;
LCD_en_write();
}
}
void delay_1us(void)
{
asm("nop");
}
void delay_nus(unsigned int n)
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1us();
}
void delay_1ms(void)
{
unsigned int i;
for (i=0;i<1140;i++);
}
void delay_nms(unsigned int n)
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1ms();
}
void start00(void)
{
DDRA = 0xFF; PORTA = 0xFF;
DDRB = 0xFF; PORTB = 0xFF;
DDRC = 0x00; PORTC = 0xFF;
DDRD = 0xFF; PORTD = 0xFF;
}
unsigned char i2c_Write(unsigned char Wdata)
{
Start();//I2C启动
Wait();
if(TestAck()!=START) return 1;//ACK
Write8Bit(wr_device_add);//写数字指南针模块的器件地址和写方式0x76
Wait();
if(TestAck()!=MT_SLA_ACK) return 2;//ACK
Write8Bit(Wdata);// 向数字指南针模块写入数据
//0xB1开始硬件补偿, 0xB1结束硬件补偿
//0xD1 正北校正
Wait();
if(TestAck()!=MT_DATA_ACK) return 4;//ACK
Stop();//I2CÍ£Ö¹
delay_nms(10);
return 0x0f;
}
unsigned char i2c_Read(unsigned char RomAddress)
{
unsigned char temp;
startr: Start();//I2C启动
Wait();
if (TestAck()!=START) goto startr;//ACK
Write8Bit(wr_device_add);// //写数字指南针模块的器件地址和写方式0x76
Wait();
if (TestAck()!=MT_SLA_ACK) return 2;//ACK
Write8Bit(RomAddress); //写数字指南针模块的内部地址0x00 0x01 0x02
Wait();
if (TestAck()!=MT_DATA_ACK) return 3;
Start();//I2C重新启动
Wait();
if (TestAck()!=RE_START) return 4;
Write8Bit(rd_device_add); //写数字指南针模块的器件地址和读方式0x77
Wait();
if(TestAck()!=MR_SLA_ACK) return 5;//ACK
Twi();//开启I2C读数据
Wait();
if(TestAck()!=MR_DATA_NOACK) return 6;//ACK
temp=TWDR;//读出数字指南针模块的数据
Stop();//I2C停止
return temp;
}
void main(void)
{ unsigned char i2c_dat;
start00();
TWBR=0x32;
TWSR=0x00;
delay_nms(2);
LCD_init();
while(1)
{ LCD_write_char(0x01,0);
delay_nms(20);
LCD_write_string(0,0,"ShuZiZhiNanZhen");
if ((PINC&0x80)==0)
{i2c_Write(0xB1);
delay_nms(2);
c=i2c_Read(0x00);
delay_nms(5);
PORTB=c;
while(1)
{if ((PINC&0x40)==0)
{i2c_Write(0xB0);
delay_nms(5);
c=i2c_Read(0x00);
delay_nms(5);
PORTB=c;
break;
delay_nms(10);}
delay_nms(1);
}
}
if ((PINC&0x20)==0)
{i2c_Write(0xD1);
i2c_dat=i2c_Read(0x00);
delay_nms(10);
}
delay_nms(2);
c=i2c_Read(0x00);
delay_nms(2);
d=i2c_Read(0x01);
delay_nms(2);
b=i2c_Read(0x02);
delay_nms(2);
PORTB=~c;
if (d==0)
{a=b;}
else if (d==1)
{
a=256+b;}
if (a>338||a<=23) LCD_write_string(0,1,"North");
if (a>23&&a<=68) LCD_write_string(0,1,"North-E");
if (a>68&&a<=113) LCD_write_string(0,1,"East");
if (a>113&&a<=158) LCD_write_string(0,1,"South-E");
if (a>158&&a<=203) LCD_write_string(0,1,"South");
if (a>203&&a<=248) LCD_write_string(0,1,"South-W");
if (a>248&&a<=293) LCD_write_string(0,1,"West");
if (a>293&&a<=338) LCD_write_string(0,1,"North-W");
bb[0]=a/100+0x30;
a=a%100;
bb[1]=a/10+0x30;
bb[2]=a%10+0x30;
LCD_write_string(10,1,bb);
delay_nms(100);
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|