51单片机学习第六课---B站UP主江协科技

DS18B20

1、基本知识讲解

2、DS18B20读取温度值

main.c

cs 复制代码
#include<regx52.h>
#include"delay.h"
#include"LCD1602.h"
#include"key.h"
#include"DS18B20.h"

float T;
void main ()
{
  LCD_Init();
  LCD_ShowString(1,1,"temp");
  
	while(1)
	{
	  DS18B20_convert();
	  T=DS18B20_read();
	  if(T<0)
	  {
	  	LCD_ShowChar(2,1,'-');	//显示负号
		T=-T;
	  }
	 else
	  {
	  	LCD_ShowChar(2,1,'+');	 //显示正号
		T=T;
	  }
	 LCD_ShowNum(2,2,T,3);	 //显示正整数  ,精度是3,-55~125
	 LCD_ShowChar(2,5,'.');		//显示小数点
	 LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示小数后面的数字,精度是4位 ,0.0623



	
	}

 }

		

onewire.c

cs 复制代码
#include<REGX52.h>
sbit onewire_DQ=P3^7;
unsigned char onewire_init()
{ 
unsigned char ackbit;
unsigned char i;
  onewire_DQ=1;
  onewire_DQ=0;
  i = 247;
  while (--i);		//延时500us
  onewire_DQ=1;
  i = 32;			//延时70us
  while (--i);
  ackbit=onewire_DQ;
  i = 247;			//延时500us,这里从机拉低60-240us会自动释放总线
  while (--i);
  return ackbit;
}
void  onewire_sendbit(unsigned char Bit)
{
   unsigned char i;
   onewire_DQ=0;
   i = 4;
   while (--i);//延时10us
   onewire_DQ=Bit;	//如果bit=0,则DQ继续拉低50us,加上前面10us,刚好满足60us.如果bit=1,则DQ相当10us后总线释放,接着继续释放50us
   	i = 24;
	while (--i);//延时50us
   onewire_DQ=1;

}
unsigned char onewire_receivebit()
{
   unsigned char i;
   unsigned char Bit;
   onewire_DQ=0;
   	i = 2;
	while (--i);//主机拉低总线5us
   onewire_DQ=1;
   	i = 2;
	while (--i);//主机释放总线5us
	Bit=onewire_DQ;//DS18B20将会发送0或1,此时主机读取数据
   	i = 24;
	while (--i);//延时50us
	return Bit;
}
void  onewire_sendbyte(unsigned char byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
  onewire_sendbit(byte&(0x01<<i));	//取一位用与
}

}
unsigned char onewire_receivebyte()
{
unsigned char i;
unsigned char byte=0x00;
for(i=0;i<8;i++)
{
 if(onewire_receivebit())
 {
 byte=byte|(0x01<<i);	   //取整体用或
 }
}
return byte;
}

DS18B20.C

cs 复制代码
#include<regx52.h>
#include"onewire.h"

#define  DS18B20_SKIP_ROM       0xCC  
#define  DS18B20_CONVERT_T       0x44	
#define  DS18B20_READ_SCRATCHPAD     0xBE


void DS18B20_convert()	   
{
   onewire_init() ;	 //初始化
   onewire_sendbyte(DS18B20_SKIP_ROM); //跳过ROM
   onewire_sendbyte(DS18B20_CONVERT_T);	//温度转换
}

float DS18B20_read()		
{  
   unsigned char TLSB,TMSB;
   int temp;
   float T;
   onewire_init() ;
   onewire_sendbyte(DS18B20_SKIP_ROM);
   onewire_sendbyte(DS18B20_READ_SCRATCHPAD);//温度读取
   TLSB=onewire_receivebyte();	 //读取低八位
   TMSB=onewire_receivebyte();	//读取高八位
   temp=(TMSB<<8)|TLSB;			//把低八位和高八位整合成一个数
   T=temp/16.0;					  //由于存储小数的缘故,最低位不是从2的0次方开始,而是2的-4方开始,所以读取的值要除以16
   return T;
}

3、DS18B20温度告警器

按键K1实现对温度上限值的加加,K2实现对温度上限值的减减,按键K3实现对温度下限值的加加,K4实现对温度下限值的减减,运用at24c02对温度上限值和下限值进行存储。超过上限值LCD1602显示ov:h,低于下限值LCD1602显示ov:l。

main.c

cs 复制代码
#include<regx52.h>
#include"delay.h"
#include"LCD1602.h"
#include"key.h"
#include"DS18B20.h"
#include"at24c02.h"
#include"timer0.h"
char Tlow,Thigh; //char类型表示数据位-127~128,满足DS18B20的测温范围-55~125
float  T,Tshow;
unsigned char keynum;
void main ()
{  
   DS18B20_convert();
   Delay(1000);
   Thigh=at24c02_readbyte(0); //一开始就读取AT24C02里的数据,这个时候还没有写入
   Tlow=at24c02_readbyte(1);
   if(Thigh>125||Tlow<-55||Thigh<=Tlow){ Thigh=25;Tlow=5;}	//读出的数据可能会超出范围,所以当超出范围时,赋初值
   LCD_Init();
   Timer0_Init();
   LCD_ShowString(1,1,"T:");
   LCD_ShowString(2,1,"TH:");
   LCD_ShowString(2,9,"TL:");
   LCD_ShowSignedNum(2,4,Thigh,3);
   LCD_ShowSignedNum(2,12,Tlow,3);
	while(1)
	{
	 keynum=key();
	 DS18B20_convert();
	 T=DS18B20_read();
	 if(T<0) {LCD_ShowChar(1,3,'-');Tshow=-T;}//为什么要定一个Tshow,主要是当T为负数时,要转为正数,这样Tshow就始终是正数
	 if(T>0) {LCD_ShowChar(1,3,'+');Tshow=T;} //因为shownum只能显示正整数,而且要显示小数部分,转成正整数方便转换
	 LCD_ShowNum(1,4,Tshow,3);
	 LCD_ShowChar(1,7,'.');	 
	 LCD_ShowNum(1,8,(unsigned long)(Tshow*100)%100,2);
	 if(keynum)
	 {
	 if(keynum==1)
	 {Thigh++;
	  if(Thigh>125){Thigh=125;}	  //温度上限值不能超过DS18B20的上限
	 }
	 if(keynum==2){
	 Thigh--;
	 if(Thigh<=Tlow)	//温度上限值减减不能减到小于温度下限值
	 {
	  Thigh++;}
	 }
	 if(keynum==3){
	 Tlow++;
	 if(Tlow>=Thigh)  //温度下限值加加不能加到大于温度上限值
	 {
	  	 Tlow--;
	 }
	 }
	 if(keynum==4)
	 {
	 Tlow--;
	  if(Tlow<-55){Tlow=-55;}	   //温度下限值不能超过DS18B20的下限
	 }
	 at24c02_writebyte(0,Thigh);   //记住写入后要延时5ms
	 Delay(5);
	 at24c02_writebyte(1,Tlow);
	 Delay(5);
     LCD_ShowSignedNum(2,4,Thigh,3);
     LCD_ShowSignedNum(2,12,Tlow,3);
}
	 if(T>Thigh){
	 LCD_ShowString(1,13,"ov:H");}	//实际温度超过设定上限值告警
	 else if(T<Tlow){
	 LCD_ShowString(1,13,"ov:L");}	  //实际温度低于设定下限值告警
	 else{LCD_ShowString(1,13,"    ");}
	 }
	}
 void Timer0_Routine()        interrupt 1
{
	static unsigned  int count;	
   	TL0 = 0x18;				
	TH0 = 0xFC;
	count++;
if(count>=20)	
{
  count=0;
  key_loop();

}



}

		

onewire.c

这里增加一步关闭中断,再打开中断

cs 复制代码
#include <REGX52.H>
sbit onewire_DQ=P3^7;
unsigned char onewire_init()
{ 
unsigned char ackbit;
unsigned char i;
  onewire_DQ=1;
  onewire_DQ=0;
  EA=0;//单总线计时时不能进入中断,因为延时是us级别,中断之后再返回会计时不准,所以这里要关掉总中断,计时完后再打开。
  i = 247;
  while (--i);		//延时500us
  onewire_DQ=1;
  i = 32;			//延时70us
  while (--i);
  ackbit=onewire_DQ;
  i = 247;			//延时500us,这里从机拉低60-240us会自动释放总线
  while (--i);
  EA=1;
  return ackbit;
}
void  onewire_sendbit(unsigned char Bit)
{
   unsigned char i;
   onewire_DQ=0;
  EA=0;
   i = 4;
   while (--i);//延时10us
   onewire_DQ=Bit;	//如果bit=0,则DQ继续拉低50us,加上前面10us,刚好满足60us.如果bit=1,则DQ相当10us后总线释放,接着继续释放50us
   	i = 24;
	while (--i);//延时50us
	  EA=1;

   onewire_DQ=1;

}
unsigned char onewire_receivebit()
{
   unsigned char i;
   unsigned char Bit;
   onewire_DQ=0;
    EA=0;
   	i = 2;
	while (--i);//主机拉低总线5us
   onewire_DQ=1;
   	i = 2;
	while (--i);//主机释放总线5us
	Bit=onewire_DQ;//DS18B20将会发送0或1,此时主机读取数据
   	i = 24;
	while (--i);//延时50us
	 EA=1;
	return Bit;
}
void  onewire_sendbyte(unsigned char byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
  onewire_sendbit(byte&(0x01<<i));	//取一位用与
}

}
unsigned char onewire_receivebyte()
{
unsigned char i;
unsigned char byte=0x00;
for(i=0;i<8;i++)
{
 if(onewire_receivebit())
 {
 byte=byte|(0x01<<i);	   //取整体用或
 }
}
return byte;
}

LCD1602

1、基本知识讲解

2、字符、字符串

2、LCD1602.c代码

cs 复制代码
#include<regx52.h>
sbit lcd_RS=P2^6;
sbit lcd_RW=P2^5;
sbit lcd_EN=P2^7;
#define port  P0
void LCD_Delay()	//@12.000MHz  1ms  //延时函数
{
	unsigned char data i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

void lcd_write_command(unsigned char command)	//写命令
{
   lcd_RS=0;
   lcd_RW=0;
   port=command;
   lcd_EN=1;
   LCD_Delay();//因为这里E脉冲宽度时间是us级别,而单片机执行一次命令是us级别,所以这里检测不到,所以加延时函数
   lcd_EN=0;
   LCD_Delay();

}
void lcd_write_Data(unsigned char Data)	 //写数据
{
   lcd_RS=1;
   lcd_RW=0;
   port=Data;
   lcd_EN=1;
   LCD_Delay();//因为这里E脉冲宽度时间是us级别,而单片机执行一次命令是us级别,所以这里检测不到,所以加延时函数
   lcd_EN=0;
   LCD_Delay();

}

void lcd_init()		  //初始化
{
 lcd_write_command(0x38);
 lcd_write_command(0x0C);
 lcd_write_command(0x06);
 lcd_write_command(0x01);
}

void LCD_setcursor(unsigned char line,unsigned char column)	  //定义光标位置,在第几行第几列
{
 if(line==1)
 {
  lcd_write_command(0x80|column-1);
 }
 else
 {
  lcd_write_command(0x80|(column-1)+0x40);
 }
}


void LCD_ShowChar(unsigned char line,unsigned char column,unsigned char Char) //显示一个字符
{
 LCD_setcursor(line,column);
 lcd_write_Data(Char);
}
void LCD_ShowString(unsigned char line,unsigned char column,unsigned char *String)	//显示字符串
{
 unsigned char i;
 LCD_setcursor(line,column);
 for(i=0;String[i]!='\0';i++)
{
lcd_write_Data(String[i]);
}
 
}
unsigned int pow(x,y)	   //定义一个幂函数	 例如x=6,y=4,则result=1*6*6*6*6=6^4
{
  unsigned char result=1;
  unsigned int i;
  for(i=0;i<y;i++)
  {
  	result*=x;
  }
  return result;
}
void LCD_ShowNum(unsigned char line,unsigned char column,unsigned int num,unsigned char length)	//显示十进制数字
{
	unsigned char i;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num/(pow(10,i-1))%10);

	
	}
	}
void LCD_ShowsignNum(unsigned char line,unsigned char column, int num,unsigned char length)//显示有符号十进制数字
{
	unsigned char i;
    unsigned int num1;
    LCD_setcursor(line,column);

 if(num>=0)
 {
  lcd_write_Data('+');
  num1=num;
 }
 else
 {
  lcd_write_Data('-');
  num1=-num;//有符号int的负数最小值为-32768,正数最大值为32767,取反会超出范围,所以定义一个无符号int   num1
 }

 	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num1/(pow(10,i-1))%10);
}
}
void LCD_ShowHexNum(unsigned char line,unsigned char column, unsigned int num,unsigned char length)	 //显示十六进制数
{
	unsigned char i;
	unsigned char SingleNum;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	SingleNum=num/(pow(16,i-1))%16;
	if(SingleNum<10)
	 {lcd_write_Data(0x30+SingleNum); }
	else
	{
	 {lcd_write_Data(0x41+SingleNum-10); }
	}
	
	}
	}
void LCD_ShowBinNum(unsigned char line,unsigned char column, unsigned int num,unsigned char length)	//显示二进制数
{
	unsigned char i;
    LCD_setcursor(line,column);
	for(i=length;i>0;i--)
	{
	 lcd_write_Data(0x30+num/(pow(2,i-1))%2);

	
	}


}

main.c

cs 复制代码
#include<regx52.h>
#include"LCD1602.h"
#include"delay.h"
void main ()
{
   lcd_init();
   LCD_ShowChar(2,4,'A');
//   LCD_ShowString(1,3,"hello");
   LCD_ShowNum(2,6,66,2);
   LCD_ShowsignNum(2,10,-77,2);
//   LCD_ShowHexNum(1,8,0x55,2);
   LCD_ShowBinNum(1,1, 0x55,8);
   LCD_ShowString(1,16,"welcome to my home!");
while(1)
{
 lcd_write_command(0x1c);	//流动字幕,移屏
 Delay(500);		
}
		
}

直流电机

1、基本知识讲解

2、LED呼吸灯

main.c

cs 复制代码
#include<regx52.h>

sbit LED=P2^0;

void Delay(unsigned int ms)
{
 while(ms--);

}
void main ()
{



while(1)
{
unsigned char i,t;
for(i=100;i>0;i--)
   {
   for(t=0;t<20;t++)
		{	
		    LED=0;
			Delay(i);
			LED=1;
			Delay(100-i);
		}
	}
for(i=0;i<100;i++)
   {
   for(t=0;t<20;t++)
		{	
		    LED=0;
			Delay(i);
			LED=1;
			Delay(100-i);
		}
	}
  
}
}

3、直流电机调速

按K1键实现电机的调速,并在数码管上显示档数。

main.c

cs 复制代码
#include<regx52.h>
#include"key.h"
#include"nixie.h"
#include"Timer0.h"
sbit motor=P1^0;
unsigned char counter,compare,keynum,speed;


void main ()
{
 Timer0_Init();


while(1)
		{
		  keynum=key();
		  if(keynum==1)
		  {
			speed++;speed%=4;
		  if(speed==0){ compare=0;}
		  if(speed==1){ compare=5;}
		  if(speed==2){ compare=50;}
		  if(speed==3){ compare=100;}
		  }
		  nixie (0,speed);

		}
}
 void Timer0_Routine()        interrupt 1
{
   	TL0 = 0x9C;				
	TH0 = 0xFF;
	counter++;
	counter%=100;
	if(counter<compare)
	{
	 motor=1;
	}
	else
	{
	 motor=0;
	}


}

ps:对达林顿管还不是很清楚

相关推荐
醉陌离39 分钟前
渗透测试学习笔记—shodan(2)
笔记·学习
OBOO鸥柏40 分钟前
OBOO鸥柏28.6寸液晶广告屏:创新技术引领智能显示新时代
人工智能·科技·大屏端·广告一体机
ZZZ_O^O1 小时前
【动态规划-卡特兰数——96.不同的二叉搜索树】
c++·学习·算法·leetcode·动态规划
Hotchip华芯邦科技1 小时前
MEMS硅麦克风应用电子烟雾化产业稳步爬升,耐高温、 防油、防酸、防腐蚀等性能优势和可实现自动化贴片及极高的一致性等特性使其必将成为主流
科技·单片机·金融·生活·社交电子·健康医疗·制造
冷心笑看丽美人2 小时前
Spring 框架七大模块(Java EE 学习笔记03)
学习·spring·架构·java-ee
huaqianzkh2 小时前
学习C#中的BackgroundWorker 组件
开发语言·学习·c#
今天我又学废了3 小时前
Scala学习记录,Array
学习
今天我又学废了3 小时前
Scala学习记录,字符串
学习
不要影响我叠Q3 小时前
《软件工程-北京大学》 学习笔记
笔记·学习