本帖最后由 dingpeng1980 于 2019-12-11 01:28 編輯
iic接口,GPIO1需要3.3V轉5v模塊
程序已經調試可以用,串口輸出晶振11.0592,波特率9600
SCL=P0^6; iic接口需要3.3V轉5v模塊
SDA=P0^7; iic接口需要3.3V轉5v模塊
GPIO1=P0^5; //模塊使能
#include<reg52.h>
#include<intrins.h>
#include<math.h>
#include "stdio.h" //需要使用printf()函數故而包含該頭文件
#define FOSC 11059200UL //系統外部時鐘頻率(無符號長整型)
#define BAUD 9600 //欲配置的串口通信波特率值
#define DISTANCE_REG 0x5E
#define SHIFT 0x35
typedef unsigned int uint;
typedef unsigned char uchar ;
float distance = 0; // 存儲計算的距離
long high = 0, low = 0; // 高字節和低字節的距離
int shift = 0; // 移位寄存器中的數值
uchar R_data;
bit R_flag=0;
sbit GPIO1=P0^5; //模塊使能
sbit SCL=P0^6; //iic接口需要3.3V轉5v模塊
sbit SDA=P0^7; //iic接口需要3.3V轉5v模塊
/*******************************************************************************
* 函數名 : Delay10us()
* 函數功能 : 延時10us
* 輸入 : 無
* 輸出 : 無
*******************************************************************************/
void Delay10us()
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
/********************************************************************
* 名稱 : Uart_Init()
* 功能 : 串口初始化,晶振11.0592,波特率9600,使能了串口中斷
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Uart_Init(void)
{
SCON=0x50; //10位數據異步通信模式,允許接收
TMOD=0x20; //設定T1工作在8位自動重裝載模式
TH1=-(FOSC/12/32/BAUD); //賦值定時初值,為了設定波特率
TL1=TH1; //賦值定時初值,為了設定波特率
TR1 = 1; //啟動T1運行控制位
ES = 1; //使能UART中斷開關ES
EA = 1; //使能單片機總中斷開關EA
}
/*******************************************************************************
* 函數名 : I2cStart()
* 函數功能 : 起始信號:在SCL時鐘信號在高電平期間SDA信號產生一個下降沿
* 輸入 : 無
* 輸出 : 無
* 備注 : 起始之后SDA和SCL都為0
*******************************************************************************/
void I2cStart()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立時間是SDA保持時間>4.7us
SDA=0;
Delay10us();//保持時間是>4us
SCL=0;
Delay10us();
}
/*******************************************************************************
* 函數名 : I2cStop()
* 函數功能 : 終止信號:在SCL時鐘信號高電平期間SDA信號產生一個上升沿
* 輸入 : 無
* 輸出 : 無
* 備注 : 結束之后保持SDA和SCL都為1;表示總線空閑
*******************************************************************************/
void I2cStop()
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();//建立時間大于4.7us
SDA=1;
Delay10us();
}
/*******************************************************************************
* 函數名 : I2cSendByte(unsigned char dat)
* 函數功能 : 通過I2C發送一個字節。在SCL時鐘信號高電平期間,保持發送信號SDA保持穩定
* 輸入 : num
* 輸出 : 0或1。發送成功返回1,發送失敗返回0
* 備注 : 發送完一個字節SCL=0,SDA=1
*******************************************************************************/
unsigned char I2cSendByte(unsigned char dat)
{
unsigned char a=0,b=0;//最大255,一個機器周期為1us,最大延時255us。
for(a=0;a<8;a++)//要發送8位,從最高位開始
{
SDA=dat>>7; //起始信號之后SCL=0,所以可以直接改變SDA信號
dat=dat<<1;
Delay10us();
SCL=1;
Delay10us();//建立時間>4.7us
SCL=0;
Delay10us();//時間大于4us
}
SDA=1;
Delay10us();
SCL=1;
while(SDA)//等待應答,也就是等待從設備把SDA拉低
{
b++;
if(b>200) //如果超過2000us沒有應答發送失敗,或者為非應答,表示接收結束
{
SCL=0;
Delay10us();
return 0;
}
}
SCL=0;
Delay10us();
return 1;
}
/*******************************************************************************
* 函數名 : I2cReadByte()
* 函數功能 : 使用I2c讀取一個字節
* 輸入 : 無
* 輸出 : dat
* 備注 : 接收完一個字節SCL=0,SDA=1.
*******************************************************************************/
unsigned char I2cReadByte()
{
unsigned char a=0,dat=0;
SDA=1; //起始和發送一個字節之后SCL都是0
Delay10us();
for(a=0;a<8;a++)//接收8個字節
{
SCL=1;
Delay10us();
dat<<=1;
dat|=SDA;
Delay10us();
SCL=0;
Delay10us();
}
return dat;
}
/********************************************************************
* 名稱 : Main()
* 功能 : 主函數
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void main()
{
GPIO1 = 1;
Uart_Init();
I2cStart();
I2cSendByte(0x80);//發送寫器件地址
I2cSendByte(SHIFT);//發送要寫入內存地址
I2cStop();
I2cStart();
I2cSendByte(0x81); //發送讀器件地址
shift = I2cReadByte(); //讀取數據
I2cStop();
SBUF = 0x00;
while(1)
{
請求并從GP2Y0E02B讀取2個地址字節
I2cStart();
I2cSendByte(0x80);//發送寫器件地址
I2cSendByte(DISTANCE_REG);//發送要寫入內存地址
I2cStop();
I2cStart();
I2cSendByte(0x81); //發送讀器件地址
high = I2cReadByte();
I2cStop();
I2cStart();
I2cSendByte(0x80);//發送寫器件地址
I2cSendByte(DISTANCE_REG+1);//發送要寫入內存地址
I2cStop();
I2cStart();
I2cSendByte(0x81); //發送讀器件地址
low = I2cReadByte();
I2cStop();
SBUF = 0x00;
distance = (high * 160 + low*10)/16/(float)pow(2,shift); // Calculate the range in mm
printf("Distance = %f\n",distance);
}
/********************************************************************
* 名稱 : Uart_Int()
* 功能 : 串口中斷子函數
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void Uart_Int(void) interrupt 4
{
EA = 0;
if(RI) //當硬件接收到一個數據時,RI會置位
{
R_data= SBUF; //這里減去48是因為從電腦中發送過來的數據是ASCII碼。
RI = 0;
R_flag=1;
}
EA = 1;
}
|