有没有大神可以帮忙写一下STC15单片机课设温度计的程序,最好每一句后面都有解释,谢谢大神

有没有大神可以帮忙写一下STC15单片机课设温度计的程序,最好每一句后面都有解释,谢谢大神,第1张

这是一个温湿度检测的程序,可以参考一下:

#include <reg52.h>

#include <intrins.h>

#include <stdio.h>

#include <string.h>

#include <absacc.h>

#include <math.h>

#define uchar unsigned char

#define uint unsigned int

sbit LcdRs=P2^0 //1602液晶端口定义

sbit LcdRw=P2^1

sbit LcdEn=P2^2

sbit led1=P3^0

sbit led2=P3^4 //报警灯端口定义

sbit ACC0=ACC^0

sbit ACC7=ACC^7

sbit k_ud=P2^4//定义上下限选择

sbit k_ws=P2^5//定义温度/湿度 选择

sbit k_add=P2^6//定义按键 +

sbit k_sub=P2^7//定义按键 -

bit flag_ud,flag_ws

bit start

uchar str[7]

//向LCD写命令

#define LCD_COMMAND 0//Command

#define LCD_DATA 1 //Data

#define LCD_CLEAR_SCREEN 0x01 //清屏

#define LCD_HOMING0X02 //光标返回原点

//设置显示模式

#define LCD_SHOW 0x04 //显示开

#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR0x02 //显示光标

#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动

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

//输入设置

#define LCD_AC_UP 0x02

#define LCD_AC_DOWN 0x00 //default

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

#define LCD_NO_MOVE 0x00 //default

unsigned char TEMP_UP=20 //温度上限

unsigned char TEMP_DOWN=0 //温度下限

unsigned char HUMUP=30//湿度上限

unsigned char HUMDOWN=10//湿度下限

unsigned char dis[4]

unsigned char LCD_Wait(void)

//SHT10设置

sbit SCK =P1^2 //定义通讯时钟端口

sbit DATA=P1^3 //定义通讯数据端口

typedef union

{ uint i//定义了两个共用体

float f

}value

enum {TEMP,HUMI}//TEMP=0,HUMI=1

#define noACK 0 //用于判断是否结束通讯

#define ACK 1 //结束数据传输

//adr command r/w

#define STATUS_REG_W 0x06 //000 0011 0

#define STATUS_REG_R 0x07 //000 0011 1

#define MEASURE_TEMP 0x03 //000 0001 1

#define MEASURE_HUMI 0x05 //000 0010 1

#define RESET0xle //000 1111 0

//定义函数

void s_transstart(void) //启动传输函数

void s_connectionreset(void) //连接复位函数

char s_write_byte(unsigned char value)//SHT10写函数

char s_read_byte(unsigned char ack)//SHT10读函数

char s_measure(unsigned char*p_value,unsigned char*p_checksum,unsigned char mode)//测量温湿度函数

void calc_dht90(float*p_humidity,float*p_temperature)//温湿度补偿

void LCD_Write(bit style, unsigned char input)

//液晶显示子程序

void delay(uint z) //延时函数

{

int x

for(x=zx>0x--)

{

int y

for(y=110y>0y--)

}

}

void dat_char(uchar ff,uchar a)

{

dis[0]=ff

dis[1]='_'

dis[2]=0x30+a/10

dis[3]=0x30+a%10

}

void LCD_Write(bit style,unsigned char input)

{

LcdRs=style

P0=input

delay(5)

LcdEn=1

delay(5)

LcdEn=0

}

void LCD_SetDisplay(unsigned char DisplayMode) //设置输出

{

LCD_Write(LCD_COMMAND,0x08|DisplayMode)

}

void LCD_SetInput(unsigned char InputMode) //设置输入

{

LCD_Write(LCD_COMMAND,0x04|InputMode)

}

void LCD_Initial()//初始化LCD函数

{

LcdEn=0

LCD_Write(LCD_COMMAND,0x38) //8位数据端口,2行显示,5*7点阵

LCD_Write(LCD_COMMAND,0x38)

LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR)//开启显示,无光标

LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN) //清屏

LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE) //AC递增,画面不动

}

void GotoXY(uchar x, uchar y) //液晶字符输入的位置

{

if(y==0)

LCD_Write(LCD_COMMAND,0x80|x)

if(y==1)

LCD_Write(LCD_COMMAND,0x80|(x-0x40))

}

void Rrint(uchar *str) //将字符输出到液晶显示

{

while(*str!='\0')

{

LCD_Write(LCD_DATA,*str)

str++

}

}

void zhuanhuan(float a) //浮点数转换成字符串函数

{

memset(str,0,sizeof(str))

sprintf(str,"%f",a)

}

void welcome() //初始界面函数

{

LCD_Initial()

GotoXY(0,0)

Rrint(" Welcome! ")

GotoXY(0,1)

Rrint(" Code of sht10 ")

delay(200)

}

/*

void delay_n10us(uint n) //延时n个10us@12M晶振

{

uint i

for(i=ni>0i--)

{

_nop_()_nop_()_nop_()

_nop_()_nop_()_nop_()

}

} */

void s_transstart(void) //启动函数

{

DATA=1SCK=0

_nop_()

SCK=1

_nop_()

DATA=0

_nop_()

SCK=0

_nop_()_nop_()_nop_()

SCK=1

_nop_()

DATA=1

_nop_()

SCK=0

}

void s_connectionreset(void) //连接复位函数

{

uchar i

DATA=1SCK=0 //Initial state

for(i=0i<9i++) //9 SCK cycles

{

SCK=1

SCK=0

}

s_transstart()

}

char s_write_byte(unsigned char value)//SHT10写字节函数

{

uchar i,error=0

for (i=0x80i>0i/=2) //shift bie for masking

{

if(i&value)DATA=1 //masking value with i,write to SENSI-BUS

else DATA=0

SCK=1

_nop_()_nop_()_nop_() //pulswith approx. 3 us

SCK=0

}

DATA=1 //release DATA-line

SCK=1 //clk#9for ack

error=DATA //check ack(DATA will be pulled down by DHT90),DATA在第9个上升沿将被DHT90自动下拉为低电平。

_nop_()_nop_()_nop_()

SCK=0

DATA=1//release DATA-line

return error //error=1 in case of no acknowledge//返回:0成功 1失败

}

//SHT10读取函数

char s_read_byte(uchar ack)

{

uchar i,val=0

DATA=1 //release DATA-line

for(i=0x80i>0i/=2)//shift bit for masking

{SCK=1

if(DATA)val=(val|i)//read bit

_nop_()_nop_()_nop_()//pulswith approx.3 us

SCK=0

}

if(ack==1)DATA=0//in case of"ack==1"pull down DATA-Line

else DATA=1//如果是校验(ack=0),读取完后结束通讯

_nop_()_nop_()_nop_() //pulswith approx. 3 us

SCK=1//clk#9 for ack

_nop_()_nop_()_nop_() //pulswith approx. 3 us

SCK=0

_nop_()_nop_()_nop_() //pulswith approx. 3 us

DATA=1 //release DATA-line

return val

}

//测量温湿度函数

char s_measure(uchar *p_value,uchar *p_checksum,uchar mode)

{

unsigned error=0

uint i

s_transstart() //transstart atart

switch(mode) //send command to sensor

{

case TEMP :error+=s_write_byte(MEASURE_TEMP)break

case HUMI :error+=s_write_byte(MEASURE_HUMI)break

default :break

}

for(i=0i<65535i++)if(DATA==0)break //wait until sensor has finishede the measurement

if(DATA)error+=1 //or timeout(~2 sec.)is reached

*(p_value) =s_read_byte(ACK) //read the first byte(MSB)

*(p_value+1)=s_read_byte(ACK) //read the second byte(LSB)

*p_checksum=s_read_byte(noACK) //read checksum

return error

}

void calc_sht90(float*p_humidity,float*p_temperature) //温湿度补偿函数

{

const float C1=-4.0//for 12 Bit

const float C2=+0.0405 //for 12 Bit

const float C3=-0.0000028 //for 12 Bit

const float T1=+0.01 //for 14 Bit@5V

const float T2=+0.00008 //for 14 Bit@5V

float rh=*p_humidity //rh: Humidity[Ticks]12 Bit

float t=*p_temperature//t: Temperature[Ticks]14 Bit

float rh_lin //rh_lin: Humidity linear

float rh_true //rh_true:Temperature compensated humidity

float t_C //t_C : Temperature[C]

t_C=t*0.01-40 //calc.temperature from ticks to [C]

rh_lin=C3*rh*rh+C2*rh+C1 //calc.humidity from ticks to[%RH]

rh_true=(t_C-25)*(T1+T2*rh)+rh_lin //calc.temperature compensated humidity[%RH]

if(rh_true>100)rh_true=100 //cut if the value is outside of

if(rh_true<0.1)rh_true=0.1 //the physical possible range

*p_temperature=t_C //return temperature[C]

*p_humidity=rh_true //return humidity[%RH]

}

void keyscan()

{

if(k_ud==0)

{

delay(10)//去抖动 100ms

if(k_ud==0)

{

while(!k_ud)

flag_ud = ~flag_ud

}

}

if(k_ws==0)

{

delay(10)//去抖动 100ms

if(k_ws==0)

{

while(!k_ws)

flag_ws = ~flag_ws

}

}

if(k_add==0)

{

delay(10)//去抖动 100ms

if(k_add==0)

{

while(!k_add)

GotoXY(12,0)

if(!flag_ws)

{

if(flag_ud){TEMP_UP++dat_char('T',TEMP_UP)}

else {TEMP_DOWN++dat_char('T',TEMP_DOWN)}

Rrint(&dis)

}

else

{

if(flag_ud){HUMUP++dat_char('H',HUMUP)}

else {HUMDOWN++dat_char('H',HUMDOWN)}

Rrint(&dis)

}

}

}

if(k_sub==0)

{

delay(10)//去抖动 100ms

if(k_sub==0)

{

while(!k_sub)

GotoXY(12,1)

if(!flag_ws)

{

if(flag_ud){TEMP_UP--dat_char('T',TEMP_UP)}

else {TEMP_DOWN--dat_char('T',TEMP_DOWN)}

Rrint(&dis)

}

else

{

if(flag_ud){HUMUP--dat_char('H',HUMUP)}

else {HUMDOWN--dat_char('H',HUMDOWN)}

Rrint(&dis)}

}

}

}

//主函数

void main()

{

value humi_val,temp_val

unsigned char error,checksum

bit status_th=0,status_ch=0

unsigned char cnt=0

LCD_Initial()

LcdRw=0

led1=0

led2=0

start=0

s_connectionreset()

welcome()//显示欢迎画面

delay(20000)

while(1)

{

cnt++

if(!(cnt%10))

{

cnt=0

error=0

error+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI)

error+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP)

if(error!=0)

{

s_connectionreset() //in case of an erroe:connection reset

}else

{

humi_val.f=(float)humi_val.i //converts integer to float

temp_val.f=(float)temp_val.i //converts integer to float

calc_sht90(&humi_val.f,&temp_val.f)//计算温度与湿?

LCD_Initial()

GotoXY(0,0)

Rrint("Tep:")

GotoXY(0,1)

Rrint("Hum:")

zhuanhuan(temp_val.f) //转换温度为uchar方便液晶显示

GotoXY(4,0)

str[5]=0xDF //℃的符号

str[6]=0x43

str[7]='\0'

Rrint(str)

if(temp_val.f>TEMP_UP-1||temp_val.f<TEMP_DOWN)

led1=1

else

led1=0

zhuanhuan(humi_val.f) //转换湿度为uchar方便液晶显示

GotoXY(4,1)

str[5]='%' //%的符号

str[6]='\0' //字符串结束标志

Rrint(str)

if((humi_val.f>HUMUP-1)||(humi_val.f<HUMDOWN))

led2=1

else

led2=0

}

}

if(!flag_ws) {GotoXY(12,0)dat_char('T',TEMP_UP)Rrint(&dis)GotoXY(12,1)dat_char('T',TEMP_DOWN)Rrint(&dis)}

else {GotoXY(12,0)dat_char('H',HUMUP)Rrint(&dis)dat_char('H',HUMDOWN)GotoXY(12,1)Rrint(&dis)}

keyscan()

}

}

下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。

软件延时:(asm)

晶振12MHZ,延时1秒

程序如下:

DELAY:MOV 72H,#100

LOOP3:MOV 71H,#100

LOOP1:MOV 70H,#47

LOOP0:DJNZ 70H,LOOP0

NOP

DJNZ 71H,LOOP1

MOV 70H,#46

LOOP2:DJNZ 70H,LOOP2

NOP

DJNZ 72H,LOOP3

MOV 70H,#48

LOOP4:DJNZ 70H,LOOP4

定时器延时:

晶振12MHZ,延时1s,定时器0工作方式为方式1

DELAY1:MOV R7,#0AH 晶振12MHZ,延时0.5秒

AJMP DELAY

DELAY2:MOV R7,#14H 晶振12MHZ,延时1秒

DELAY:CLR EX0

MOV TMOD,#01H设置定时器的工作方式为方式1

MOV TL0,#0B0H给定时器设置计数初始值

MOV TH0,#3CH

SETB TR0 开启定时器

HERE:JBC TF0,NEXT1

SJMP HERE

NEXT1:MOV TL0,#0B0H

MOV TH0,#3CH

DJNZ R7,HERE

CLR TR0 定时器要软件清零

SETB EX0

RET

C语言延时程序:

10ms延时子程序(12MHZ)

void delay10ms(void)

{

unsigned char i,j,k

for(i=5i>0i--)

for(j=4j>0j--)

for(k=248k>0k--)

}

1s延时子程序(12MHZ)

void delay1s(void)

{

unsigned char h,i,j,k

for(h=5h>0h--)

for(i=4i>0i--)

for(j=116j>0j--)

for(k=214k>0k--)

}

200ms延时子程序(12MHZ)

void delay200ms(void)

{

unsigned char i,j,k

for(i=5i>0i--)

for(j=132j>0j--)

for(k=150k>0k--)

}

500ms延时子程序程序: (12MHZ)

void delay500ms(void)

{

unsigned char i,j,k

for(i=15i>0i--)

for(j=202j>0j--)

for(k=81k>0k--)

}

下面是用了8.0000MHZ的晶振的几个延时程序(用定时0的工作模式1):

(1)延时0.9MS

void delay_0_9ms(void)

{

TMOD=0x01/*定时器0工作在模式1下(16位计数器)*/

TH0=0xfd

TL0=0xa8

TR0=1/*启动定时器*/

while(TF0==0)

TR0=0

}

(2)延时1MS

void delay_1ms(void)

{

TMOD=0x01/*定时器0工作在模式1下(16位计数器)*/

TH0=0xfd

TL0=0x65

TR0=1/*启动定时器*/

while(TF0==0)

TR0=0

}

(3)延时4.5ms

void delay_4_5ms(void)

{

TMOD=0x01/*定时器0工作在模式1下(16位计数器)*/

TH0=0xf4

TL0=0x48

TR0=1/*启动定时器*/

while(TF0==0)

TR0=0

}

#include <reg51.H>

#include <intrins.H>

typedef unsigned char INT8U

typedef unsigned int INT16U

sfr IAP_DATA= 0xC2

sfr IAP_ADDRH = 0xC3

sfr IAP_ADDRL = 0xC4

sfr IAP_CMD = 0xC5

sfr IAP_TRIG= 0xC6

sfr IAP_CONTR = 0xC7

#define DEBUG_DATA 0x5A //本测试程序最终存储在 EEPROM 单元的数值

#define DATA_FLASH_START_ADDRESS 0x00 //STC5Axx 系列 EEPROM 测试起始地址

union union_temp16

{

INT16U un_temp16

INT8U un_temp8[2]

}my_unTemp16

INT8U Byte_Read(INT16U add) //读一字节,调用前需打开IAP 功能

void Byte_Program(INT16U add, INT8U ch) //字节编程,调用前需打开IAP 功能

void Sector_Erase(INT16U add) //擦除扇区

void IAP_Disable() //关闭IAP 功能

void Delay()

void main (void)

{

INT16U eeprom_address

INT8U read_eeprom

P1 = 0xF0 //演示程序开始,让 P1[3:0] 控制的灯亮

Delay() //延时

P1 = 0x0F //演示程序开始,让 P1[7:4] 控制的灯亮

Delay() //延时

//将EEPROM 测试起始地址单元的内容读出

eeprom_address = DATA_FLASH_START_ADDRESS //将测试起始地址送eeprom_address

read_eeprom = Byte_Read(eeprom_address) //读EEPROM的值,存到read_eeprom

if (DEBUG_DATA == read_eeprom)

{ //数据是对的,亮 P1.7 控制的灯,然后在 P1 口上将 EEPROM 的数据显示出来

P1 = ~0x80

Delay() //延时

P1 = ~read_eeprom

}

else

{ //数据是错的,亮 P1.3 控制的灯,然后在 P1 口上将 EEPROM 的数据显示出来

//再将该EEPROM所在的扇区整个擦除,将正确的数据写入后,亮 P1.5 控制的灯

P1 = ~0x08

Delay() //延时

P1 = ~read_eeprom

Delay() //延时

Sector_Erase(eeprom_address) //擦除整个扇区

Byte_Program(eeprom_address, DEBUG_DATA)//将 DEBUG_DATA 写入 EEPROM

P1 = ~0x20//熄灭 P1.3 控制的灯,亮 P1.5 控制的灯

}

while (1) //CPU 在此无限循环执行此句

}

//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节

INT8U Byte_Read(INT16U add)

{

IAP_DATA = 0x00

IAP_CONTR = ENABLE_ISP//打开IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x01//IAP/ISP/EEPROM 字节读命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

return (IAP_DATA)

}

//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据

void Byte_Program(INT16U add, INT8U ch)

{

IAP_CONTR = ENABLE_ISP//打开 IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x02//IAP/ISP/EEPROM 字节编程命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

IAP_DATA = ch //要编程的数据先送进IAP_DATA 寄存器

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

}

//擦除扇区, 入口:DPTR = 扇区地址

void Sector_Erase(INT16U add)

{

IAP_CONTR = ENABLE_ISP//打开IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x03//IAP/ISP/EEPROM 扇区擦除命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

}

void IAP_Disable()

{

//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

IAP_CONTR = 0 //关闭IAP 功能

IAP_CMD = 0 //清命令寄存器,使命令寄存器无命令,此句可不用

IAP_TRIG = 0 //清命令触发寄存器,使命令触发寄存器无触发,此句可不用

IAP_ADDRH = 0

IAP_ADDRL = 0

}

void Delay()

{

INT8U i

INT16U d=5000

while (d--)

{

i=255

while (i--)

}

}


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

原文地址: https://outofmemory.cn/yw/12001551.html

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

发表评论

登录后才能评论

评论列表(0条)

保存