这几天调试AT89S52 ——MLX90614 ,一直无应答。是移植IIC过来的,不知道为啥老是无应答。
参考了
http://www.ourdev.cn/forum.php?mod=viewthread&tid=3990328 这个帖子 还是失败。
一直找不到原因,电路上我是用10K电阻上拉的。
代码如下:
- #include "reg52.h"
- #include <intrins.h>
- #include <stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- //************函数声明*****************************************************
- void start(); //MLX90614发起始位子程序
- void stop(); //MLX90614发结束位子程序
- uchar ReadByte(void); //MLX90614接收字节子程序
- //void send_bit(void); //MLX90614发送位子程序
- void SendByte(uchar number); //MLX90614接收字节子程序
- void read_bit(void); //MLX90614接收位子程序
- void delay(uint N); //延时程序
- uint readtemp(void); //读温度数据
- void init1602(void); //LCD初始化子程序
- void busy(void); //LCD判断忙子程序
- void delayscan(i);
- //************数据定义****************************************************
- bdata uchar flag1; //可位寻址数据
- sbit bit_out=flag1^7;
- sbit bit_in=flag1^0;
- sbit SCK=P1^7;
- sbit SDA=P1^6;
- //i2c总线
- //sbit scl = P2^2;
- //sbit sda = P2^3;
- sbit SCL=P1^7;
- uchar tempH,tempL,err;
- //************************** mlx90614 ***********************************
- //command mode 命令模式
- #define RamAccess 0x00 //对RAM操作
- #define EepomAccess 0x20 //对EEPRAM操作
- #define Mode 0x60 //进入命令模式
- #define ExitMode 0x61 //退出命令模式
- #define ReadFlag 0xf0 //读标志
- #define EnterSleep 0xff //进入睡眠模式
- //ram address read only RAM地址(只读)
- #define AbmientTempAddr 0x03 //周围温度
- #define IR1Addr 0x04
- #define IR2Addr 0x05
- #define LineAbmientTempAddr 0x06 //环境温度
- /*0x0000 0x4074 16500 0.01/单元
- -40 125*/
- #define LineObj1TempAddr 0x07 //目标温度,红外温度
- /*0x27ad-0x7fff 0x3559 22610 0.02/单元
- -70.01-382.19 0.01 452.2*/
- #define LineObj2TempAddr 0x08
- //eepom address EEPROM地址
- #define TObjMaxAddr 0x00 //测量范围上限设定
- #define TObjMinAddr 0x01 //测量范围下限设定
- #define PWMCtrlAddr 0x02 //PWM设定
- #define TaRangeAddr 0x03 //环境温度设定
- #define KeAddr 0x04 //频率修正系数
- #define ConfigAddr 0x05 //配置寄存器
- #define SMbusAddr 0x0e //器件地址设定
- #define Reserverd1Addr 0x0f //保留
- #define Reserverd2Addr 0x19 //保留
- #define ID1Addr 0x1c //ID地址1
- #define ID2Addr 0x1d //ID地址2
- #define ID3Addr 0x1e //ID地址3
- #define ID4Addr 0x1f //ID地址4
- #define _Nop() _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
- #define delayNOP(); { _nop_();_nop_();_nop_();_nop_();_nop_();};// _nop()_=1 CPU cycle
- typedef bit BOOL ;
- uchar CHACK;
- uchar aa;
- #define Nack_number 10
- bit ack;
- sbit rs = P2^6 ;
- sbit rw = P3^6 ;
- sbit ep = P2^7 ;
- void delayms(uchar) ;
- void lcd_wcmd(uchar) ;
- BOOL lcd_bz() ;
- void lcd_pos(uchar) ;
- void lcd_wdat(uchar) ;
- void display(uchar,uchar *) ;
- union
- {
- uchar c[2]; //c[0]为X的高位,c[1]为X的底位,
- int x;
- }Temp;
- uchar dis1[16] ;
- uchar dis2[16] ;
- /*void delay2ms()
- {
- byte i;
- for(i=0xff;i!=0;i--)
- {Wdt();} //4*1.085*256
- }
- void delay2(void)
- {
- byte i;
- for(i=2;i!=0;i--);
- }
- */
- void longdelay(uchar s) //长延时
- {
- while(s--)
- {
- delayms(60) ;
- }
- }
- void delayms(uchar ms)
- { // 延时子程序
- uchar i ;
- while(ms--)
- {
- for(i = 0 ; i<250;i++) ;
- }
- }
- void delay_nus(unsigned int n) //N us延时函数
- {
- unsigned int i=0;
- for (i=0;i<n;i++)
- _nop_();
- }
- BOOL lcd_bz()
- { // 测试LCD忙碌状态
- BOOL result ;
- rs = 0 ;
- rw = 1 ;
- ep = 1 ;
- result = (BOOL)(P0 & 0x80) ;
- ep = 0 ;
- return result ;
- }
- void lcd_wcmd(uchar cmd)
- { // 写入指令数据到LCD
- while(lcd_bz()) ;
- rs = 0 ;
- rw = 0 ;
- ep = 0 ;
- P0 = cmd ;
- ep = 1 ;
- ep = 0 ;
- }
- void lcd_pos(uchar pos)
- { //设定显示位置
- lcd_wcmd(pos | 0x80) ;
- }
- void lcd_wdat(uchar dat)
- { //写入字符显示数据到LCD
- while(lcd_bz()) ;
- rs = 1 ;
- rw = 0 ;
- ep = 0 ;
- P0 = dat ;
- ep = 1 ;
- ep = 0 ;
- }
- void lcd_init()
- { //LCD初始化设定
- lcd_wcmd(0x38) ; //function set
- delayms(1) ;
- lcd_wcmd(0x38) ; //function set
- delayms(1) ;
- lcd_wcmd(0x08) ; //display on/off
- delayms(1) ;
- lcd_wcmd(0x01) ; //清除LCD的显示内容
- delayms(1) ;
- lcd_wcmd(0x06) ; //entry mode set
- delayms(1) ;
- lcd_wcmd(0x0F) ; //entry mode set
- delayms(1) ;
- }
- /*---------------
- 函数名称:display()
- 功能 :在LCD上显示数组的数据
- 说明 :先写显示地址,后写显示数据
- 调用 :lcd_wcmd(), lcd_pos()
- 入口参数:pos 写入的位置,q指向要写入的数据所在的数组
- 返回值 :无
- ----------------*/
- void display(uchar pos, uchar *q)
- {
- uchar i ;
- //lcd_wcmd(0x01) ; //clear
- delayms(10) ;
- lcd_pos(pos) ;
- for(i=0 ;i<16;i++)
- {
- lcd_wdat(*q) ;
- q++ ;
- // longdelay(2) ;
- }
- }
- void init_serial(void)
-
- {
- //定时器1的工作方式2
- TMOD=0x20; //装载计数初值
- TL1=0xfd;
- TH1=0xfd; //采用串口工作方式1,无奇偶校验
- SCON=0x50; //串口波特率不加倍
- PCON=0x00; //开总中断,开串口中断
- IE=0x90; //启动定时器1
- TR1=1;
- }
- void comsend(uchar ch) //串口发送数据 发送一个数据
- {
- // TB8=0;
- SBUF = ch;
- while(!TI);
- TI=0;
- }
- /*--------------------------------------------------------------------------
- 函数名: start_bit
- 功能: 在SMBus总线上产生起始状态
- 注解: 参考"系统管理总线说明书-版本2.0"
- --------------------------------------------------------------------------*/
- void start_bit()
- {
- // _SDA_OUTPUT; //设置SDA为输出
- SDA=1; //设置SDA线为高电平
- //_nop_(); _nop_();
- SCL=1; //设置SCL线为高电平
- delayNOP(); //在终止和起始状态之间产生总线空闲时间(Tbuf=4.7us最小值)
- SDA=0; //设置SDA线为低电平
- delayNOP();
- //(重复)开始状态后的保持时间,在该时间后,产生第一个时钟信号 //Thd:sta=4us最小值
- SCL=0; //设置SCL线为低电平
- //_nop_(); _nop_();
- }
- /*------------------------------------------------------------------------
- 函数名: stop_bit
- 功能: 在SMBus总线上产生终止状态
- 注解: 参考"系统管理总线说明书-版本2.0"
- ------------------------------------------------------------------------*/
- void stop_bit()
- {
- // _SDA_OUTPUT; //设置SDA为输出
- SDA=0;
- SCL=1;
- delayNOP(); //延时5us
- SDA=1;
- delayNOP();
- SCL=0; //终止状态建立时间(Tsu:sto=4.0us最小值)
- //设置SDA线为高电平
- }
- /*-------------------------------------------------------------
- 函数名: send_bit
- 功能:在SMBus总线上发送一位数据
- //-------------------------------------------------------------*/
- void send_bit(unsigned char bit_out)
- {
-
- // _SDA_OUTPUT; //设置SDA为开漏输出以在总线上传送数据
- if(bit_out==1) //核对字节的位
- SDA=1; //如果bit_out=1,设置SDA线为高电平
- else
- SDA=0; //如果bit_out=0,设置SDA线为低电平
- //delayNOP(); //
- SCL=1; //设置SCL线为高电平
- delayNOP(); //时钟脉冲高电平脉宽(10.6us)
- SCL=0; //设置SCL线为低电平
- delayNOP(); //时钟脉冲低电平脉宽
- }
- /*------------------------------------------------------------
- 函数名: receive_bit
- 功能:在SMBus总线上接收一位数据
- //---------------------------------------------------------*/
- unsigned char receive_bit()
- {
- unsigned char bit_in;
- SDA=1; //设置SDA为高阻输入
- SCL=1; //设置SCL线为高电平
- delay_nus(1);
- if(SDA==1) //从总线上读取一位,赋给bit_in
- bit_in=1;
- else
- bit_in=0;
- delay_nus(1);
- SCL=0; //设置SCL线为低电平
- delay_nus(2);
- return bit_in; //返回bit_in值
- }
- /*-----------------------------------------------------------
- 函数名: slave_ack
- 功能: 由受控器件MLX90614中读取确认位
- 返回值: unsigned char ack
- 1 - ACK
- 0 - NACK
- //-----------------------------------------------------------*/
- unsigned char slave_ack()
- {
- unsigned char ack;
- ack=0;
- SDA=1; //设置SDA为高阻输入
- SCL=1; //设置SCL线为高电平
- delayNOP();
- if(SDA==1) //从总线上读取一位,赋给ack
- ack=0;
- else
- ack=1;
- //delay_nus(1);
- SCL=0; //设置SCL线为低电平
- // delay_nus(2);
- return ack;
- }
- /*--------------------------------------------------------
- 发送一个字节
- 函数名: TX_byte
- 功能: 在SMBus总线上发送一个字节
- 参数: unsigned char TX_buffer (将要在总线上发送的字节)
- 注解: 先发送字节的高位
- //--------------------------------------------------------*/
- void TX_byte(unsigned char TX_buffer)
- {
- unsigned char idata n = 8;
- while(n--)
- {
- if(0x80==(TX_buffer&0x80))
- {
- SDA = 1 ; //传送 1
- SCL = 1 ;
- delayNOP();
- SCL = 0 ;
- SDA = 0 ;
-
- }
- else
- {
- SDA = 0; //传送 0
- SCL = 1;
- delayNOP();
- SCL = 0;
- }
- TX_buffer = TX_buffer<<1; //左移一位
- delayNOP();
- }
- delayNOP();
- //check_ACK(); //
- //return (CHACK);
-
- }
- /*------------------------------------------------------
- 接收一个字节
- 函数名: RX_byte
- 功能: 在SMBus总线上接收一个字节
- 参数: unsigned char ack_nack (确认位)
- 0 - 主控器件发送 ACK
- 1 - 主控器件发送 NACK
- 返回值: unsigned char RX_buffer (总线接收的字节)
- 注解: 先接收字节的高位
- //-------------------------------------------------------*/
- unsigned char RX_byte(unsigned char ack_nack)
- {
- unsigned char RX_buffer;
- unsigned char Bit_counter;
- for(Bit_counter=8;Bit_counter;Bit_counter--)
- {
- if(receive_bit()==1) //由SDA线读取一位
- {
- RX_buffer<<=1; //如果位为"1",赋"1"给RX_buffer
- RX_buffer|=0x01;
- }
- else //如果位为"0",赋"0"给RX_buffer
- {
- RX_buffer<<=1;
- RX_buffer&=0xfe;
- }
- }
- send_bit(ack_nack); //发送确认位
- return RX_buffer;
- }
- //-------------------------------------------------------------//
- /*---------------------------------------------------
- 由MLX90614 RAM/EEPROM 读取的数据
- 函数名: MEM_READ
- 功能: 给定受控地址和命令时由MLX90614读取数据
- 参数: unsigned char slave_addR (受控地址)
- unsigned char cmdR (命令)
- 返回值: unsigned long int Data
- //-------------------------------------------------*/
- unsigned long int MEM_READ(unsigned char slave_addR, unsigned char cmdR)
- {
- unsigned char DataL; //
- unsigned char DataH; //由MLX90614读取的数据包
- unsigned char PEC; //
- unsigned long int Data; //由MLX90614返回的寄存器数值
- unsigned char Pecreg; //存储计算所得PEC字节
- unsigned char arr[6]; //存储已发送字节的缓冲器
- unsigned char ack_nack;
- unsigned char SLA;
- SLA=(slave_addR<<1);
- begin:
- start_bit(); //发送起始位
- TX_byte(SLA);
- delayNOP(); //发送受控器件地址,写命令
- if(slave_ack()==0)
- {
- comsend(0xaa);
- stop_bit();
- goto begin;
- } //发送命令
- comsend(0xBB);
- TX_byte(cmdR);
- if(slave_ack()==0)
- {
- stop_bit();
- goto begin;
- }
- start_bit(); //发送重复起始位
- TX_byte(SLA+1); //发送受控器件地址,读命令
- if(slave_ack()==0)
- {
- stop_bit();
- goto begin;
- }
- DataL=RX_byte(0);
- DataH=RX_byte(0); //读取两个字节数据
- PEC=RX_byte(ack_nack); //读取MLX90614的PEC码
- if(ack_nack==1) //主控器件发送ack 或是 nack 取决于pec计算,如果PEC是不正确的,发送nack并返回到goto begin
- {
- stop_bit();
- goto begin;
- }
- stop_bit(); //发送终止位
- arr[5]=(SLA);
- arr[4]=cmdR;
- arr[3]=(SLA+1);
- arr[2]=DataL;
- arr[1]=DataH;
- arr[0]=0;
- // Pecreg=PEC_cal(arr,6); //调用计算 CRC 的函数
- if(PEC==Pecreg)
- {
- ack_nack=0;
- }
- else
- {
- ack_nack=0;
- }
- Data=(DataH*256)+DataL;
- return Data;
- }
- void main()
- {
- uint Tem,yy; //温度变量
- uchar tm1,tm2;
- unsigned char slaveaddress;
- unsigned long int DATA;
- unsigned int *mahm;
- lcd_init();
- init_serial() ;
- SCL=1;
- delay_nus(1200);
- SCL=0; //
- delay_nus(1200); //SMBus request,Switch PWM mode to SMBus mode(at least 2ms)
- SCL=1; //
- while(1)
- {
- slaveaddress=MEM_READ(0x00,0x2E); //Get the slave address which stored in EEPROM "0Eh"
- DATA=MEM_READ(slaveaddress,0x07); //Read Object Temperature from MLX90614 RAM 07h
-
- tm1 =DATA%256;
- tm2= DATA/256;
- comsend(tm2);
- comsend(tm1);
- sprintf(dis2,"%d",DATA);
- display(0x00,dis2);
- delayms(10);
-
- }
- /*while(1)
- {
- Tem=readtemp(); //读取温度
- tm1 =Tem%256;
- tm2= Tem/256;
- comsend(tm2);
- comsend(tm1);
- sprintf(dis2,"%d",Tem);
- display(0x00,dis2);
- delayms(10);
- } */
- }
复制代码
一周热门 更多>