logo资料库

MLX90614和STC12C5604AD的SMBus&PWM;_通信.doc

第1页 / 共23页
第2页 / 共23页
第3页 / 共23页
第4页 / 共23页
第5页 / 共23页
第6页 / 共23页
第7页 / 共23页
第8页 / 共23页
资料共23页,剩余部分请下载后查看
1目的
2C 代码
2.1由MLX90614读取温度部分
实例给出了应用C语言来实现从MLX90614中读取物体温度的程序。为了使程序操作和运
2.2写入数据到MLX90614部分(改变发射率、改变SMBus地址、改变PWMCTRL配置)
2.3子文件对应的.h文件介绍
3根据PWM 输出模式计算温度读数
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 1 目的 该文档的主要目的是描述怎样实现单片机和红外温度计 MLX90614 的 SMBus 通信,并简略介绍利用单片 机对 MLX90614 的 PWM 输出脉冲进行测量并计算相关温度。代码是基于 STC12C5604AD 单片机的。实例给 出了由 C 语言实现 MLX90614 读取物体温度,写入数据到 MLX90614、以及对 PWM 脉冲的测量和计算等功 能。 2 C 代码 2.1 由MLX90614 读取温度部分 实例给出了应用 C 语言来实现从 MLX90614 中读取物体温度的程序。为了使程序操作和运行简单起见, 整个项目被分为几个子项目。在该文档中整个 C 程序分为主文件 SMBus.c (用来实现对物体温度的读取、改 变 SMBus 地址、改变发射率、以及改变 PWMCTRL 配置参数功能);子文件 SMBus_CM.c(具体描述 SMBus 通信的起始状态,终止状态,发送和接受数据); 子文件 SMBus_OP.c(包含了利用 SMBus 通信由 MLX90614 读取数据,对 MLX90614 写入数据和 PEC 校验码计算的程序);子文件 Delay.c(调用延迟函 数);子文件 dec2hex.c(将十进制转换为十六进制);子文件 CalTem.c(根据十六进制数值计算温度读 数);子文件 digitalLED.c(在数字 LEDs 上显示温度读数)。在主文件的头文件中引用相应的子文件.h 文 件,以将所有功能综合、链接起来。 //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// 主文件 SMBus.c //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// 红外温度计—MLX90614 中读取物体温度 描述:该文件是基于单片机 STC12C5604AD 编写的 C 语言程序,可通过 SMBus 实现对 MLX90614 温度数据 的读取,对 MLX90614 写入数据的功能。实例给出了读取物体温度的程序,以及可根据十六进制数值计算温度 数值并在数字 LEDs 上显示温度的程序,但是此为可选项,用户可根据自己的应用另行选择其他方式。 //----------------------------------------------------------------------------------------------------------------------------------------// 头文件 //----------------------------------------------------------------------------------------------------------------------------------------// #include #include "stdio.h" #include "intrins.h" #include "string.h" #include "SMBus_CM.h" #include "SMBus_OP.h" #include "digitalLED.h" #include "CalTem.h" #include "dec2hex.h" #include "Delay.h" //----------------------------------------------------------------------------------------------------------------------------------------// 宏定义 I/O 端口和 SMBus 信号输入输出方向 //----------------------------------------------------------------------------------------------------------------------------------------// #define _SDA_OUTPUT P1M0=0x10; P1M1=0x10; #define _SDA_INPUT P1M0=0x10; P1M1=0x00; #define _SCL_IO P1M0=0x08; P1M1=0x08; //引用 SMBus_CM.h 文件(包含起始状态,终止状态,发送,接收字节等) //引用 SMBus_OP.h 文件(包含由 MLX90614 中读取数据和写入数据) //引用 digitalLED.h 文件以在数字 LEDs 上显示温度读数 //引用 CalTem.h 文件来根据十六进制数值计算温度 //引用 dec2hex.h 文件将十进制转换为十六进制 //引用 Delay.h 文件 //设置 SDA 为开漏输出 //设置 SDA 为高阻输入 //设置 SCL 为开漏输出的 I/O 端口 1 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 sbit SDA = P1^4; sbit SCL = P1^3; //----------------------------------------------------------------------------------------------------------------------------------------// 主函数功能 作用:读取物体温度 //----------------------------------------------------------------------------------------------------------------------------------------// void main() { //指定 SDA 线给 P14 //指定 SCL 线给 P13 unsigned char slaveaddress; unsigned long int DATA; unsigned int *mahm; _SCL_IO; _SDA_OUTPUT; //引用宏定义-设置 SCL 为开漏式 I/O 口 //引用宏定义-设置 SDA 为开漏式输出 SCL=0; Delay(1200); SCL=1; while(1) { // //SMBus 请求时间,将 PWM 模式转换为 SMBus 模式(至少为 2ms) // slaveaddress=MEM_READ(0x00,0x2E); //读取存于 MLX90614 EEPROM "0Eh"地址中的 SMBus 地址 DATA=MEM_READ(slaveaddress,0x07); //基于上述地址由 MLX90614 的内存 07h 中读取物体温度 mahm=CALTEMP(DATA); //基于所得的十六进制温度格式计算实际温度 show(mahm,5); //在数字 LEDs 上显示计算所得温度 } } //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// 子文件 SMBus_CM.c //----------------------------------------------------------------------------------------------------------------------------------------// 该文档包含了 SMBus 通信的起始状态,终止状态,发送和接受字节等 //----------------------------------------------------------------------------------------------------------------------------------------// 头文件 //----------------------------------------------------------------------------------------------------------------------------------------// #include #include "SMBus_CM.h" #include "intrins.h" #include "Delay.h" //----------------------------------------------------------------------------------------------------------------------------------------// 宏定义 I/O 端口和 SMBus 信号的方向 //----------------------------------------------------------------------------------------------------------------------------------------// #define _SDA_OUTPUT P1M0=0x10; P1M1=0x10; #define _SDA_INPUT P1M0=0x10; P1M1=0x00; #define _SCL_IO P1M0=0x08; P1M1=0x08; sbit SDA = P1^4; sbit SCL = P1^3; //设置 SDA 为开漏输出 //设置 SDA 为高阻输入 //设置 SCL 为开漏式 I/O 端口 //指定 SDA 线给 P14 //指定 SCL 线给 P13 //头文件中引用本身 2 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 //----------------------------------------------------------------------------------------------------------------------------------------// 函数名: start_bit 功能: 在 SMBus 总线上产生起始状态 注解: 参考“系统管理总线说明书-版本 2.0” //----------------------------------------------------------------------------------------------------------------------------------------// void start_bit() { //设置 SDA 为输出 //设置 SDA 线为高电平 _SDA_OUTPUT; SDA=1; _nop_();_nop_(); SCL=1; Delay(5); SDA=0; Delay(5); //(重复)开始状态后的保持时间,在该时间后,产生第一个时钟信号 //Thd:sta=4us 最小值 //设置 SCL 线为低电平 SCL=0; _nop_();_nop_(); //设置 SCL 线为高电平 //在终止和起始状态之间产生总线空闲时间(Tbuf=4.7us 最小值) //设置 SDA 线为低电平 } //----------------------------------------------------------------------------------------------------------------------------------------// 函数名: stop_bit 功能: 在 SMBus 总线上产生终止状态 注解: 参考“系统管理总线说明书-版本 2.0” //----------------------------------------------------------------------------------------------------------------------------------------// void stop_bit() { _SDA_OUTPUT; SCL=0; Delay(5); SDA=0; Delay(5); SCL=1; Delay(5); SDA=1; //设置 SDA 为输出 //设置 SCL 线为低电平 //设置 SDA 线为低电平 //设置 SCL 线为高电平 //终止状态建立时间(Tsu:sto=4.0us 最小值) //设置 SDA 线为高电平 } //----------------------------------------------------------------------------------------------------------------------------------------// 函数名: send_bit 功能:在 SMBus 总线上发送一位数据 //----------------------------------------------------------------------------------------------------------------------------------------// void send_bit(unsigned char bit_out) { _SDA_OUTPUT; //设置 SDA 为开漏输出以在总线上传送数据 if(bit_out==0) else SDA=0; SDA=1; _nop_(); _nop_(); _nop_(); //核对字节的位 //如果 bit_out=1,设置 SDA 线为高电平 //如果 bit_out=0,设置 SDA 线为低电平 // //Tsu:dat=250ns 最小值 // 3 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 SCL=1; Delay(4); SCL=0; Delay(4); //设置 SCL 线为高电平 //时钟脉冲高电平脉宽(10.6us) //设置 SCL 线为低电平 //时钟脉冲低电平脉宽 } //----------------------------------------------------------------------------------------------------------------------------------------// 函数名: receive_bit 功能:在 SMBus 总线上接收一位数据 //----------------------------------------------------------------------------------------------------------------------------------------// unsigned char receive_bit() { } //----------------------------------------------------------------------------------------------------------------------------------------// 函数名: slave_ack 功能: 由受控器件 MLX90614 中读取确认位 返回值: unsigned char ack 1 - ACK 0 - NACK //----------------------------------------------------------------------------------------------------------------------------------------// unsigned char slave_ack() { } //----------------------------------------------------------------------------------------------------------------------------------------// 发送一个字节 函数名: TX_byte 功能: 在 SMBus 总线上发送一个字节 参数: unsigned char TX_buffer (将要在总线上发送的字节) 注解: 先发送字节的高位 unsigned char bit_in; _SDA_INPUT; SCL=1; Delay(2); if(SDA==1) bit_in=1; else bit_in=0; Delay(2); SCL=0; Delay(4); return bit_in; unsigned char ack; ack=0; _SDA_INPUT; SCL=1; Delay(2); if(SDA==1) ack=0; else ack=1; Delay(2); SCL=0; Delay(4); return ack; //设置 SDA 为高阻输入 //设置 SCL 线为高电平 //从总线上读取一位,赋给 bit_in //设置 SCL 线为低电平 //返回 bit_in 值 //设置 SDA 为高阻输入 //设置 SCL 线为高电平 //从总线上读取一位,赋给 ack //设置 SCL 线为低电平 4 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 //----------------------------------------------------------------------------------------------------------------------------------------// void TX_byte(unsigned char TX_buffer) { unsigned char Bit_counter; unsigned char bit_out; for(Bit_counter=8;Bit_counter;Bit_counter--) { if(TX_buffer&0x80) else bit_out=1; bit_out=0; send_bit(bit_out); TX_buffer<<=1; } //如果 TX_buffer 的当前位是 1,设置 bit_out 为 1 //否则,设置 bit_out 为 0 //发送 SMBus 总线上的当前位 //核对下一位 } //----------------------------------------------------------------------------------------------------------------------------------------// 接收一个字节 函数名: 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) { } else { } RX_buffer<<=1; RX_buffer|=0x01; RX_buffer<<=1; RX_buffer&=0xfe; } send_bit(ack_nack); return RX_buffer; //由 SDA 线读取一位 //如果位为“1”,赋“1”给 RX_buffer //如果位为“0”,赋“0”给 RX_buffer //发送确认位 } //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// 子文件 SMBus_OP.c //----------------------------------------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------------------------------------// 该文档包含了 SMBus 通信时从 MLX90614 读取数据,写入数据和 PEC 校验码计算的程序 5 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 //头文件中引用本身 //引用 SMBus_CM.h 文件 //----------------------------------------------------------------------------------------------------------------------------------------// 头文件 //----------------------------------------------------------------------------------------------------------------------------------------// #include #include "SMBus_CM.h" #include "intrins.h" #include "SMBus_OP.h" #include "Delay.h" //----------------------------------------------------------------------------------------------------------------------------------------// sbit SDA = P1^4; sbit SCL = P1^3; //----------------------------------------------------------------------------------------------------------------------------------------// 计算 PEC 包裹校验码 函数名: PEC_cal 功能: 根据接收的字节计算 PEC 码 参数: unsigned char pec[], int n 返回值: pec[0] - 该字节包含计算所得 crc 数值 注解: 参考“系统管理总线说明书-版本 2.0”和应用指南“MCU 和 MLX90614 的 SMBus 通信" //----------------------------------------------------------------------------------------------------------------------------------------// unsigned char PEC_cal(unsigned char pec[],int n) { //指定 MLX90614 的 SDA 线给单片机 P14 引脚 //指定 MLX90614 的 SCL 线给单片机 P13 引脚 unsigned char crc[6]; unsigned char Bitposition=47; unsigned char shift; unsigned char i; unsigned char j; unsigned char temp; do{ crc[5]=0; crc[4]=0; crc[3]=0; crc[2]=0; crc[1]=0x01; crc[0]=0x07; Bitposition=47; shift=0; //在传送的字节中找出第一个“1” i=5; j=0; while((pec[i]&(0x80>>j))==0 && (i>0)) //载入 CRC 数值 0x000000000107 //设置 Bitposition 的最大值为 47 //设置最高标志位 (包裹字节标志) //字节位标志,从最低位开始 { Bitposition--; if(j<7) { j++; } else { j=0x00; i--; } }//while 语句结束,并找出 Bitposition 中为“1”的最高位位置 shift=Bitposition-8; //得到 CRC 数值将要左移/右移的数值“shift” //对 CRC 数据左移“shift”位 6 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 if((crc[i-1]&0x80) && (i>0)) while(shift) for(i=5;i<0xFF;i--) { } { { temp=1; } else { temp=0; } crc[i]<<=1; crc[i]+=temp; //核对字节的最高位的下一位是否为"1" //是 - 当前字节 + 1 //否 - 当前字节 + 0 //实现字节之间移动“1” shift--; } //pec 和 crc 之间进行异或计算 for(i=0;i<=5;i++) pec[i]^=crc[i]; { } }while(Bitposition>8); return pec[0]; //返回计算所得的 crc 数值 } //----------------------------------------------------------------------------------------------------------------------------------------// 由 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; unsigned char PEC; unsigned long int Data; unsigned char Pecreg; unsigned char arr[6]; unsigned char ack_nack; unsigned char SLA; SLA=(slave_addR<<1); begin: // //由 MLX90614 读取的数据包 // //由 MLX90614 返回的寄存器数值 //存储计算所得 PEC 字节 //存储已发送字节的缓冲器 start_bit(); TX_byte(SLA); if(slave_ack()==0) { stop_bit(); goto begin; } TX_byte(cmdR); if(slave_ack()==0) //发送起始位 //发送受控器件地址,写命令 //发送命令 7 / 23
C 语言代码 MLX90614 和单片机STC12C5604AD 的SMBus,PWM 通信 //发送重复起始位 //发送受控器件地址,读命令 { stop_bit(); goto begin; } start_bit(); TX_byte(SLA+1); if(slave_ack()==0) { stop_bit(); goto begin; } DataL=RX_byte(0); 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); if(PEC==Pecreg) ack_nack=0; { } else { DataH=RX_byte(0); PEC=RX_byte(ack_nack); if(ack_nack==1) //取决于 pec 计算,如果 PEC 是不正确的,发送 nack 并返回到 goto begin { // //读取两个字节数据 // //读取 MLX90614 的 PEC 码 //主控器件发送 ack 或是 nack //发送终止位 //调用计算 CRC 的函数 ack_nack=1; } Data=(DataH*256)+DataL; return Data; } //----------------------------------------------------------------------------------------------------------------------------------------// MLX90614 EEPROM 中写入数据 函数名: EEPROM_WRITE 功能: 根据命令写入相关数据到给定受控器件地址的 MLX90614 参数: unsigned char slave_addW (受控器件地址) unsigned char cmdW (命令) unsigned char DataL unsigned char DataH //----------------------------------------------------------------------------------------------------------------------------------------// void EEPROM_WRITE(unsigned char slave_addW,unsigned char cmdW,unsigned char DataL,unsigned char DataH) { //存储计算所得 PEC 字节 unsigned char Pecreg; unsigned char SLA; 8 / 23
分享到:
收藏