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

数字信号与模拟信号

模拟信号:连续的

数字信号:离散的,只有0和1两种状态

用灯做例子,如果一个开关只能控制灯的亮和灭,就是传递数字信号,如果这个开关能控制亮的多少,比如30%,66%这种,就是传递模拟信号

AD与DA

1、基本知识讲解

 2、运算放大器

 

 3、AD模数转换

LCD1602显示屏显示电位器、热敏电阻、光敏电阻的阻值

xpt2046.c

#include<regx52.h>
sbit XPT_CS=P3^5;
sbit XPT_DCLK=P3^6;
sbit XPT_DIN=P3^4;
sbit XPT_DOUT=P3^7;

unsigned int read_AD(unsigned char command)
{ 
  unsigned int value=0;
  unsigned char i;
 
   XPT_DCLK=0;
   XPT_CS=0;
  for(i=0;i<8;i++)
  {
  XPT_DIN=command&(0x80>>i);  //写字命令
  XPT_DCLK=1;
  XPT_DCLK=0;
  }
  

   for(i=0;i<16;i++)
   {
   XPT_DCLK=1;
   XPT_DCLK=0;
   if( XPT_DOUT)
   {
   value=value|(0x8000>>i);	  //读16位数据,注意存放顺序从高位到低位
   }
   }
   XPT_CS=1;
   if(command&0x08)	   //8位分辨率,则右移8位,因为从高位开始读,也就是实际8位数存放在高8位,右移8位才是实际数值
 {return value>>8;}
   else
 {return value>>4;}	//12位分辨率,所以右移4位就行

 }

xpt2046.h

#ifndef  __XPT2046_H__
#define  __XPT2046_H__
 //8位分辨率
#define XP_8  0x9c //电位器正
#define VBAT_8  0xAC //GR正  光敏电阻 
#define YN_8  0xCC
#define YP_8  0xDC	//NTC正  热敏电阻
#define AUX_8  0xEC
//12位分辨率
#define XP_12  0x94
#define VBAT_12  0xA4
#define YN_12  0xC4
#define YP_12  0xD4
#define AUX_12  0xE4
   			unsigned int read_AD(unsigned char command);
#endif

main.c

#include<regx52.h>
#include"Delay.h"
#include"xpt2046.h"
#include"lcd1602.h"

unsigned int value;

void main ()
{
  LCD_Init();
  LCD_ShowString(1,1,"ADJ   RG   NTC");

while(1)
		{
			  value=read_AD(XP_12);
			  LCD_ShowNum(2,1,value,4);
			  Delay(100);
			  value=read_AD(VBAT_12);
			  LCD_ShowNum(2,7,value,4);
			  Delay(100);
			  value=read_AD(YP_12);
			  LCD_ShowNum(2,13,value,4);
			  Delay(100);
		}
}

4、DA数模转换

通过定时器结合DA实现呼吸灯的效果

main.c

#include<regx52.h>
#include"delay.h"
#include"Timer0.h"
sbit DA=P2^1;
unsigned char counter,compare;
unsigned char i;

void main ()
{
 Timer0_Init();


while(1)
		{
		  for(i=0;i<100;i++)
		  {
		   compare=i;
		   Delay(10);
		  }
		  for(i=100;i>0;i--)
		  {
		   compare=i;
		    Delay(10);
		  }
		}
}
 void Timer0_Routine()        interrupt 1
{
   	TL0 = 0x9C;				
	TH0 = 0xFF;
	counter++;
	counter%=100;
	if(counter<compare)
	{
	DA=1;
	}
	else
	{
	DA=0;
	}


}

红外遥控(外部中断)

1、基本知识讲解

 

 

 2、红外遥控

按下遥控器在LCD1602显示屏上显示地址码和命令码,长按实现累加、累减

main.c

#include<regx52.h>
#include"delay.h"
#include"LCD1602.h"
#include"IR.h"
unsigned char Address,Command,num;
void main ()
{	   
LCD_Init();
IR_init();
LCD_ShowString(1,1,"ADDR  CMD    NUM");
LCD_ShowString(2,1,"00    00     000");
while(1)
{
  if(IR_GetDataFlag()||IR_GetRepeatFlag())	  
  {
  	Address=IR_GetAddressFlag();
	Command=IR_GetCommandFlag();
 
  LCD_ShowHexNum(2,1,Address,2);
  LCD_ShowHexNum(2,7,Command,2);
  if(Command==IR_VOL_ADD){num++;}
  if(Command==IR_VOL_MINUS){num--;}
  LCD_ShowNum(2,14,num,3);
}
}
} 

IR.C 

#include"Int0.h"
#include"Timer0.h"
#include<regx52.h>
unsigned int IR_Time;  //存储定时器计时的时间
unsigned char IR_state;	//红外状态位,0表示空闲状态,为高电平,1表示工作状态,为低电平

unsigned char IR_Data[4]; //用数组存储32位数据
unsigned char IR_pData;	//用指针数组表示32位数据

unsigned char IR_DataFlag;//收到数据标志位
unsigned char IR_RepeatFlag; //重复标志位
unsigned char IR_Address; //地址码
unsigned char IR_Command; //命令码


void IR_init() //红外遥控初始化
{
  int0_init();
  Timer0_Init();
}
  unsigned char IR_GetDataFlag()  //红外遥控获取收到数据帧标志位,1为收到,0为没收到
  {
	    if(IR_DataFlag)
	         {IR_DataFlag=0;return 1;}
	    else
	         {return 0;}
  }
  unsigned char IR_GetRepeatFlag() // 红外遥控获取收到连发帧标志位,是否收到连发帧,1为收到,0为未收到
  {
	    if(IR_RepeatFlag)
	        {IR_RepeatFlag=0;return 1;}
	    else
	        {return 0;}
  }
unsigned char IR_GetCommandFlag()//红外遥控获取收到的命令数据
{return(IR_Command);}
unsigned char IR_GetAddressFlag() //红外遥控获取收到的地址数据
{return(IR_Address);}


 void Int0_Routine()        interrupt 0	 //外部中断0,下降沿触发
{

 
	  if(IR_state==0)	//这里把高电平空闲状态写为0,1是低电平
	  {
	  
	   Timer0_setcounter(0);  //定时器清0
	   Timer0_run(1); //开始计时
	   IR_state=1;	  //置状态为1
	  } 

  else if(IR_state==1)//状态1,等待Start信号或Repeat信号
  {
 
		   IR_Time=Timer0_Getcounter();	//获取上一次中断到此次中断的时间
		   Timer0_setcounter(0);  //定时计数器清0
		   if(IR_Time>13500-500&&IR_Time<13500+500)	//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)
		   { 
		   	IR_state=2;	  	//置状态为2
		   }
		   else if(IR_Time>11250-500&&IR_Time<11250+500) //如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)
		   {
				IR_RepeatFlag=1; //置收到连发帧标志位为1
				Timer0_run(0);//定时器停止
		   		IR_state=0;	//置状态为0
		   }
		
		   else	 		 //接收出错
		   {
		   		IR_state=1;
		   }
  }
   else if(IR_state==2)	 //状态2,接收数据
   {
			   IR_Time=Timer0_Getcounter();	//获取上一次中断到此次中断的时间
			   Timer0_setcounter(0);//定时计数器清0
			   if(IR_Time>1120-500&&IR_Time<1120+500)//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)
				{
				IR_Data[IR_pData/8]&=~(0x01<<IR_pData%8);  //数据对应位清0
				IR_pData++;	//数据位置指针自增
		   		}
			  else if(IR_Time>2250-500&&IR_Time<2250+500)  	//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)
			  {
				IR_Data[IR_pData/8]|=(0x01<<IR_pData%8);//数据对应位置1
				IR_pData++;//数据位置指针自增
			  }
			  else	 	//接收出错
			  {
			   IR_pData=0; //数据位置指针清0
			   IR_state=1; 	//置状态为1
			  }
   

   if(IR_pData>31) //如果接收到了32位数据
   {
   	 IR_pData=0; //数据位置指针清0
	 if((IR_Data[0]==~IR_Data[1])&&	(IR_Data[2]==~IR_Data[3])) //数据验证
	 {
	   IR_Address=IR_Data[0];//转存数据
	   IR_Command=IR_Data[2];
	   IR_DataFlag=1;	//置收到数据标志位为1

	 }
	   Timer0_run(0);  //定时器停止
	   IR_state=0; //置状态为0
}
}
}


Timer0.c 

#include<regx52.h>
void Timer0_Init()		//1毫秒@12.000MHz  软件生成的代码
{
	//AUXR &= 0x7F;			//定时器时钟12T模式,旧版本单片机是12MHZ,不需要再设置为12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0;				//设置定时初始值
	TH0 = 0;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 0;				//定时器0不计时
}
void Timer0_setcounter(unsigned int value)
{
TH0=value/256;
TL0=value%256;
}

unsigned int Timer0_Getcounter()
{
return (TH0<<8)|TL0;

}

void Timer0_run(unsigned char Flag)
{
TR0=Flag;
}

Int0.c 

#include<regx52.h>
void int0_init()
{
IT0=1;
IE0=0;
EX0=1;
EA=1;
PX0=1;
}


// void Int0_Routine()        interrupt 0
//{
//   
//}

3、红外遥控直流电机调速

遥控器按0电机不转,按1,以50%的转速转动; 按2,以80%的转速转动;按3,以100%的转速转动;

main.c

#include<regx52.h>
#include"key.h"
#include"nixie.h"
#include"Motor.h"
#include"IR.h"
unsigned char keynum,speed;
unsigned char command;

void main ()
{
Motor_init();
IR_init();

while(1)
		{

		  if(IR_GetDataFlag())
		  {
		   command=IR_GetCommandFlag();
		   if(command==IR_0){speed=0;}
		   if(command==IR_1){speed=1;}
		   if(command==IR_2){speed=2;}
		   if(command==IR_3){speed=3;}
		  }
		 
		
		  if(speed==0){ Motor_setspeed(0);}
		  if(speed==1){ Motor_setspeed(50);}
		  if(speed==2){ Motor_setspeed(80);}
		  if(speed==3){ Motor_setspeed(100);}
		 
		  nixie (0,speed);
	   }
		}

https://blog.csdn.net/FMgxth/article/details/135093632?fromshare=blogdetail&sharetype=blogdetail&sharerId=135093632&sharerefer=PC&sharesource=m0_51664996&sharefrom=from_link

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值