51单片机程序编写

51单片机程序编写,第1张

/*这是用LCD显示所测温度的代码,你参考一下,如果没问题的话,其他的功能你再添加就好了,不难*/

#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

#define Nack_number 10

//**************端口定义**************************************************

uchar flag    //LCD控制线接口

sbit RS=P1^0  //RS端

sbit RW=P1^1  //读写端

sbit LCDE=P2^5  //使能端

//mlx90614端口定义

sbit SCK=P2^1 //时钟线

sbit SDA=P2^2 //数据线

//************数据定义****************************************************

bdata uchar flag1 //可位寻址数据

sbit bit_out=flag1^7

sbit bit_in=flag1^0

uchar tempH,tempL,err

//**************************  LCD1602  ***********************************

//向LCD写入命令或数据*****************************************************

#define LCD_COMMAND 0       //命令

#define LCD_DATA 1       // 数据

#define LCD_CLEAR_SCREEN 0x01       // 清屏

#define LCD_HOMING   0x02       // 光标返回原点

//设置显示模式******* 0x08+   *********************************************

#define LCD_SHOW 0x04     //显示开

#define LCD_HIDE 0x00     //显示关

#define LCD_CURSOR 0x02 //显示光标

#define LCD_NO_CURSOR 0x00     //无光标

#define LCD_FLASH 0x01     //光标闪动

#define LCD_NO_FLASH 0x00     //光标不闪动

//设置输入模式********** 0x04+ ********************************************

#define LCD_AC_UP 0x02     //光标右移 AC+

#define LCD_AC_DOWN 0x00       //默认 光标左移 AC-

#define LCD_MOVE 0x01       //画面可平移

#define LCD_NO_MOVE 0x00       //默认 画面不移动

//**************************  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

//************函数声明*****************************************************

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 cmd_wrt(uchar cmd) //LCD写命令子程序

void dat_wrt(uchar dat) //LCD写数据子程序

void display(uint Tem) //显示子程序

void Print(uchar *str) //字符串显示程序

//*************主函数*******************************************

void main()

{

uint Tem //温度变量

SCK=1

SDA=1

delay(4)

SCK=0

delay(1000)

SCK=1

init1602() //初始化LCD

while(1)

{

Tem=readtemp() //读取温度

cmd_wrt(0x01) //清屏

Print("  Temperature:    ") //显示字符串  Temperature: 且换行

display(Tem) //显示温度

Print(" ^C") //显示摄氏度

delay(10000) //延时再读取温度显示

}

}

void Print(uchar *str) //字符串显示程序

{

while(*str!='\0') //直到字符串结束

{

dat_wrt(*str) //转成ASCII码

str++ //指向下一个字符

}

}

//*********输入转换并显示*********

void display(uint Tem)

{

uint T,a,b

T=Tem*2

if(T>=27315) //温度为正

{

T=T-27315 //

a=T/100 //温度整数

b=T-a*100 //温度小数

if(a>=100) //温度超过100度

{

dat_wrt(0x30+a/100) //显示温度百位

dat_wrt(0x30+a%100/10) //显示温度十位

dat_wrt(0x30+a%10) //显示温度个位

}

else if(a>=10) //温度超过10度

{

dat_wrt(0x30+a%100/10) //显示温度十位

dat_wrt(0x30+a%10) //显示温度个位

}

else //温度不超过10度

{

dat_wrt(0x30+a) //显示温度个位

}

dat_wrt(0x2e) //显示小数点

if(b>=10) //温度小数点后第1位数不等于0

{

dat_wrt(0x30+b/10) //显示温度小数点后第1位数

dat_wrt(0x30+b%10) //显示温度小数点后第2位数

}

else //温度小数点后第1位数等于0

{

dat_wrt(0x30) //显示温度小数点后第1位数0

dat_wrt(0x30+b) //显示温度小数点后第2位数

}

}

else //温度为负

{

T=27315-T

a=T/100

b=T-a*100

dat_wrt(0x2d) //显示负号

if(a>=10) //温度低于负10度

{

dat_wrt(0x30+a/10) //显示温度十位

dat_wrt(0x30+a%10) //显示温度个位

}

else //温度高于负10度

{

dat_wrt(0x30+a) //显示温度个位

}

dat_wrt(0x2e) //显示小数点

if(b>=10) //温度小数点后第1位数不等于0

{

dat_wrt(0x30+b/10) //显示温度小数点后第1位数

dat_wrt(0x30+b%10) //显示温度小数点后第2位数

}

else //温度小数点后第1位数等于0

{

dat_wrt(0x30) //显示温度小数点后第1位数0

dat_wrt(0x30+b) //显示温度小数点后第2位数

}

}

}

//************************************

void start(void) //停止条件是 SCK=1时,SDA由1到0

{

SDA=1

delay(4)

SCK=1

delay(4)

SDA=0

delay(4)

SCK=0

delay(4)

}

//------------------------------

void stop(void) //停止条件是 SCK=1时,SDA由0到1

{

SCK=0

delay(4)

SDA=0

delay(4)

SCK=1

delay(4)

SDA=1

}

//---------发送一个字节---------

void SendByte(uchar number)

{

uchar i,n,dat

n=Nack_number //可以重发次数

Send_again:

dat=number

for(i=0i<8i++) //8位依次发送

{

if(dat&0x80)   //取最高位

{

bit_out=1    //发1

}

else

{

bit_out=0    //发0

}

send_bit()    //发送一个位

dat=dat<<1    //左移一位

}

read_bit()  //接收1位 应答信号

if(bit_in==1)     //无应答时重发

{

stop()

if(n!=0)

{

n--    //可以重发Nack_number=10次

goto Repeat //重发

}

else

{

goto exit //退出

}

}

else

{

goto exit

}

Repeat:

start() //重新开始

goto Send_again //重发

exit: //退出

}

//-----------发送一个位---------

void send_bit(void)

{

if(bit_out==1)

{

SDA=1  //发1

}

else

{

SDA=0  //发0

}

_nop_()

SCK=1  //上升沿

delay(4)delay(4)

SCK=0

delay(4)delay(4)

}

//----------接收一个字节--------

uchar ReadByte(void)

{

uchar i,dat

dat=0 //初值为0

for(i=0i<8i++)

{

dat=dat<<1 //左移

read_bit() //接收一位

if(bit_in==1)

{

dat=dat+1 //为1时对应位加1

}

}

SDA=0 //发送应答信号0

send_bit()

return dat //带回接收数据

}

//----------接收一个位----------

void read_bit(void)

{

SDA=1 //数据端先置1

bit_in=1

SCK=1 //上升沿

delay(4)delay(4)

bit_in=SDA //读数据

_nop_()

SCK=0

delay(4)delay(4)

}

//------------------------------

uint readtemp(void)

{

SCK=0

start() //开始条件

SendByte(0x00) //发送从地址00

SendByte(0x07) //发送命令

start() //开始条件

SendByte(0x01) //读从地址00

bit_out=0

tempL=ReadByte() //读数据低字节

bit_out=0

tempH=ReadByte() //读数据高字节

bit_out=1

err=ReadByte() //读错误信息码

stop() //停止条件

return(tempH*256+tempL)

}

//******************LCD显示子函数***********************

void init1602(void) //初始化LCD

{

cmd_wrt(0x01) //清屏

cmd_wrt(0x0c) //开显示,不显示光标,不闪烁

cmd_wrt(0x06) //完成一个字符码传送后,光标左移,显示不发生移位

cmd_wrt(0x38) //16×2显示,5×7点阵,8位数据接口

}

void busy(void) //LCD忙标志判断

{

flag=0x80 //赋初值 高位为1 禁止

while(flag&0x80) //读写 *** 作使能位禁止时等待 继续检测

{

P0=0xff

RS=0 //指向地址计数器

RW=1 //读

LCDE=1 //信号下降沿有效

flag=P0 //读状态位 高位为状态

LCDE=0

}

}

void cmd_wrt(uchar cmd) //写命令子函数

{

LCDE=0

busy() //检测 读写 *** 作使能吗

P0=cmd //命令

RS=0 //指向命令计数器

RW=0 //写

LCDE=1 //高电平有效

LCDE=0

}

void dat_wrt(uchar dat) //写数据子函数

{

busy() //检测 读写 *** 作使能吗

LCDE=0

if(flag==16)

{

RS=0 //指向指令寄存器

RW=0 //写

P0=0XC0 //指向第二行

LCDE=1 //高电平有效

LCDE=0

}

RS=1 //指向数据寄存器

RW=0 //写

P0=dat //写数据

LCDE=1 //高电平有效

LCDE=0

}

//------------延时--------------

void delay(uint n)

{

uint j

for(j=0j<nj++)

{

_nop_()

}

}

当然可以用stc89s52单片机来读取温度了,但是,mlx90614采用的是SMbus 总线协议,你要用单片机引脚来模拟总线,并要写出读取温度的程序,要根据SMbus 总线协议来写呀,能写吗?

与单片机只需要两个脚连接就行了,类似于I2C总线的连接方式,但是通信协议可不同的。如下图


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11854103.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存