1、/*/*大气压检测GY68 BMP180 模块编译器编写手头上有块BMP180气压传感模块,为了好玩,想用之作一车载气压表。在网上找AVR驱动未果,就用来自网络BMP085模块C51单片机IIC测试程序修改,测试成功,方便初学AVR的参考;听说BMP180航模上也可以用。效果图:模块:GY68 BMP180 编译器:winavr V2.0.8单片机:MEGA16作者:十堰供电 DXY*/* #include #include #include #define SDA68_L PORTB &= (1PB0) #define SDA68_H PORTB |= (1PB0)#define SCL68
2、_L PORTB &= (1PB1) #define SCL68_H PORTB |= (1PB1)#define SDA68_DDR_0 DDRB &= (1PB0)#define SDA68_DDR_1 DDRB |= (1PB0) #define SCL68_DDR_0 DDRB &= (1PB1)#define SCL68_DDR_1 DDRB |= (1PB1)#define SDA68_RD_VAL(PINB & _BV(PB0)#define BMP085_SlaveAddress 0xee /定义器件在IIC总线中的从地址 #define OSS 0 / Oversamplin
3、g Setting (note: code is not set up to use other OSS values)#define uchar unsigned char int dis_data; /变量short ac1;short ac2; short ac3; unsigned short ac4;unsigned short ac5;unsigned short ac6;short b1; short b2;short mb;short mc;short md;uchar HorL;uchar ge,shi,bai,qian,wan,shiwan;/*起始信号*/void BMP
4、085_Start(void) SDA68_H; /拉高数据线 SCL68_H;SDA68_DDR_1;SCL68_DDR_1; /拉高时钟线 _delay_us(5); /延时 SDA68_L; /产生下降沿 _delay_us(5); /延时 SCL68_L; /拉低时钟线SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1;/*停止信号*/void BMP085_Stop(void) SDA68_L; /拉低数据线 SCL68_H; SDA68_DDR_1;SCL68_DDR_1; /拉高时钟线 _delay_us(5); /延时 SDA68_H; /产生上升沿 _delay_
5、us(5); /延时SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1;/*发送应答信号入口参数:ack (0:ACK 1:NAK)*/void BMP085_SendACK(uchar ack)SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1;if (ack) SDA68_H;/写应答else SDA68_L; SCL68_H; /拉高时钟线 _delay_us(5); /延时 SCL68_L; /拉低时钟线 _delay_us(5); /延时SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1;/*接收应答信号*/uchar BMP085_RecvACK
6、(void) SCL68_H; /拉高时钟线 SDA68_DDR_0;/拉低,置为输入SCL68_DDR_1;_delay_us(5); /延时 if (SDA68_RD_VAL) HorL =1;else HorL =0; SCL68_L; /拉低时钟线 _delay_us(5); /延时SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1;return HorL;/*向IIC总线发送一个字节数据*/void BMP085_SendByte(char dat) SDA68_DDR_1;/DDRA |=_BV(PA0);SCL68_DDR_1;uchar i; for (i=0; i
7、8; i+) /8位计数器 /dat = 1; /移出数据的最高位 /SDA68 = CY; /送数据口 if (dat&0x80) SDA68_H;else SDA68_L;dat = 1;SCL68_H; /拉高时钟线 _delay_us(5); /延时 SCL68_L; /拉低时钟线 _delay_us(5); /延时 SDA68_DDR_1;/拉高,置为输出SCL68_DDR_1; BMP085_RecvACK();/*从IIC总线接收一个字节数据*/uchar BMP085_RecvByte(void) uchar i,dat = 0; SDA68_H;SDA68_DDR_1; /使
8、能内部上拉,准备读取数据,for (i=0; i8; i+) /8位计数器 dat=1;SCL68_H;SCL68_DDR_0;_delay_us(5);dat |= SDA68_RD_VAL;SCL68_L;SCL68_DDR_1;_delay_us(5);return dat;/*/读出BMP085内部数据,连续两个/*short Multiple_read(uchar ST_Address) uchar msb, lsb; short _data; BMP085_Start(); /起始信号 BMP085_SendByte(BMP085_SlaveAddress); /发送设备地址+写信
9、号 BMP085_SendByte(ST_Address); /发送存储单元地址 BMP085_Start(); /起始信号 BMP085_SendByte(BMP085_SlaveAddress+1); /发送设备地址+读信号 msb = BMP085_RecvByte(); /BUF0存储 BMP085_SendACK(0); /回应ACK lsb = BMP085_RecvByte(); BMP085_SendACK(1); /最后一个数据需要回NOACK BMP085_Stop(); /停止信号 _delay_ms(5); _data = msb 15; x2 = (long) mc
10、4; /* conver085(temperature); lcd_show_char(1,0,bai); /LCD显示,根据显示位置修改 lcd_show_char(1,1,shi); lcd_show_char(1,3,ge); /* b6 = b5 - 4000; x1 = (b2 * (b6 * b6 12) 11; x2 = ac2 * b6 11; x3 = x1 + x2; b3 = (long)ac1 * 4 + x3) + 2)/4; x1 = ac3 * b6 13; x2 = (b1 * (b6 * b6 12) 16; x3 = (x1 + x2) + 2) 2; b4
11、 = (ac4 * (unsigned long) (x3 + 32768) 15; b7 = (unsigned long) up - b3) * (50000 OSS); if( b7 8) * (p 8); x1 = (x1 * 3038) 16; x2 = (-7357 * p) 16; pressure = p + (x1 + x2 + 3791) 4);conver085(pressure);lcd_show_char(2,4,shiwan); /LCD显示,根据显示位置修改 lcd_show_char(2,5,wan); lcd_show_char(2,6,qian); lcd_
12、show_char(2,7,bai); lcd_show_char(2,9,shi);lcd_show_char(2,10,ge);/* altitude=44330.0*(1.0-pow(float)(pressure)/101325.0,1.0/5.255); /根据芯片手册提供的公式计算海拔高度altitude *= 100; /转换成厘米单位的高度值,调用时再换算成带小数的高度值,提高精度 conver085(altitude);lcd_show_char(1,8,shiwan); /LCD显示,根据显示位置修改 lcd_show_char(1,9,wan); lcd_show_cha
13、r(1,10,qian); lcd_show_char(1,11,bai);lcd_show_char(1,13,shi);lcd_show_char(1,14,ge); /*/*主程序*/*int main(void) DDRA=0xff;PORTA=0xff;DDRC=0xff;PORTC=0xff; _delay_ms(50); /上电延时 init_lcd(); /液晶初始化lcd_show_char(1,2,.); lcd_show_char(1,4,0XDF); /温度单位 lcd_show_char(1,5,C); lcd_show_char(1,12,.);lcd_show_char(1,15,m);/高度单位lcd_show_char(2,2,P); /显示压强 lcd_show_char(2,3,:); lcd_show_char(2,8,.); lcd_show_char(2,11,h); /气压单位 lcd_show_char(2,12,p); lcd_show_char(2,13,a);Init_BMP085(); /初始化BMP085 while(1) /循环 bmp085Convert(); _delay_ms(500);