蓝桥杯单片机

蓝桥杯单片机

或非门(英语:NOR gate)是一种基本的逻辑门电路,当它的两个输入同时为低电平时,输出为高电平;当任一输入为高电平时,输出为低电平。或非门的符号是"|",或非门的真值表如下:

输入A输入B输出
001
010
100
110

或非门在数字电路设计中有广泛的应用,例如在组合逻辑电路中,可以用来实现逻辑函数的计算。

1T和12T指的是时钟周期和机器周期之间的关系,机器周期=(1/时钟频率 )* T模式

在1T模式下,系统外部时钟为12MHz晶振工作的12分频,每个系统周期就是1us

Led底层

void Led_Show(unsigned char addr,flag)
{
	static unsigned char temp = 0x00;
	static unsigned char temp_old = 0xff;
	if(flag)
		temp |= 0x01<<addr;
	else
		temp &= ~(0x01<<addr);
	if(temp != temp_old)
	{
		P0 = ~temp;
		P2 = P2 & 0x1f | 0x80;
		P2 &= 0x1f;
		
		temp_old = temp;
	}
}

数码管

数码管展示函数代码

unsigned char Nixie_num[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x88};
unsigned char Nixie_wei[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

unsigned char Nixie_Show(unsigned char wei,num,point)
{
   //消影操作
    P0 = 0xff;
    P2 = P2&0x1f|0xe0;
    P2 &= 0x1f;//关闭锁存器
    
    //数码管位选
    P0 = Nixie_wei[wei];
    P2 = P2&0x1f | 0xc0;
    P2 &= 0x1f;//关闭锁存器
    
    //数码管段选
    P0 = Nixie_num[num];
    if(point)
      P0 &= 0x7f;//如果有小数点则加上小数点
    P2 = P2&0x1f|0xe0;
    P2 &= 0x1f;//关闭锁存器
    
}

位选通道

将锁存器HC573的Y6端口打开P2 = (P2 &0x1f)| 0xc0;

八位数码管分别是 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80

段选通道

将锁存器HC573的Y7端口打开 P2 = (P2&0x1f)|0xe0;

DS18B20

第一步:初始化DS18B20

第二步:跳过ROM指令(Skip Rom)0xCC

第三步:执行温度转换(CONVERT)0x44

再次初始化,再次跳过ROM,执行读取暂存器(READ SCRATCHPAD)0xbe

(high<<8)|low/精度

float Read_T()
{
  unsigned char TH,TL;
  DS18B20_Init();
  DS18B20_SendByte(0xCC);//发送跳过rom指令
  DS18B20_SendByte(0x44);//执行温度转换命令
  
  DS18B20_Init();//再次初始化
  DS18B20_SendByte(0xCC);//发送跳过ROM指令
  DS18B20_SendByte(0xbe);//执行读取暂存器指令
  
  TL = DS18B20_ReadByte();//先读低字节
  TH = DS18B20_ReadByte();
  return ((TH<<8)|TL)/16.0;
}
//设置精度可以不用记
#define DS18B20_RESOLUTION_12  0x7F  //精度为0.0625	 750ms该时间为最大转换时间
#define DS18B20_RESOLUTION_11  0x5F	 //精度为0.125	375ms
#define DS18B20_RESOLUTION_10  0x3F  //精度为0.25	187.5ms
#define DS18B20_RESOLUTION_9   0x1F  //精度为0.5   93.75ms 
void DS18B20_WriteByte(unsigned char Command)
{//DS18B20执行写入暂存寄存器指令
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_WRITE_SCRATCHPAD);
	OneWire_SendByte(0x7F);//写入第一个字节为TH
	OneWire_SendByte(0x00);//写入第二个字节为TL
	OneWire_SendByte(Command);//写入第三个字节为分辨率,即精度
}

NE555

采用定时器T0做计数器时,将P34引脚和signal连接可捕获脉冲;采用T1做计数器时,需要将P35引脚连接signal。

#include <STC15F2K60S2.H>
unsigned int freq;
unsigned int time_1s;
// 计数器0
void Timer0Init(void) // 0微秒@12.000MHz
{
    AUXR &= 0x7F; // 定时器时钟12T模式
    TMOD &= 0xF0; // 设置定时器模式
  
    TMOD |= 0x05;//不自动重装 0101  后两位01表示16位不自动重装载模式  第三位置1做计数器,置0做定时器
  
    TL0 = 0x00; // 设置定时初值
    TH0 = 0x00; // 设置定时初值
    TF0 = 0;    // 清除TF0标志
    TR0 = 1;    // 定时器0开始计时
}
// 定时器1
void Timer1Init(void) // 1毫秒@12.000MHz
{
    AUXR &= 0xBF; // 定时器时钟12T模式
    TMOD &= 0x0F; // 设置定时器模式
    TL1 = 0x18;   // 设置定时初值
    TH1 = 0xFC;   // 设置定时初值
    TF1 = 0;      // 清除TF1标志
    TR1 = 1;      // 定时器1开始计时
    ET1 = 1;      // 允许定时器1中断
    EA = 1;       // 允许总中断
}
void Timer1Sever() interrupt 3
{
    if (++time_1s == 1000)
    {
        time_1s = 0;
        // 1秒定时器中断
        freq = TH0 << 8 | TL0; // 读取计数器0当前值
        TH0 = 0;
        TL0 = 0;
    }
}
void main()
{
}

超声波

sbit Tx = P1^0;
sbit RX = P1^1;

void wave_init()
{
  unsigned char i;
  for(i = 0;i<8;i++)
  {//发送8个方波
    TX = 1;
    Delay12us();
    TX = 0;
    Delay12us();
  }
}
unsigned int ut_wave_data()
{
  unsigned int time;
  TMOD &= 0x0f;//不影响定时器0  使用定时器1
  TH1 = TL1 = 0;//清空计数
  wave_init();//发送方波
  TR1 = 1;//定时器1开始计时
  while((RX == 1) && (TF1 == 0));//定时器没有溢出,并且也没有收到值,则卡住
  TR1 = 0;//停止计时
  if(TF1 == 0)
  {//如果没有溢出,则表示正常收到信号
    time = TH1<<8 | TL1;
    return (time*0.017);
  }
  else
  {//如果溢出,清除溢出标志位
    TF1 = 0;
    return 0;
  }
  
}
sbit Tx = P1^0;
sbit RX = P1^1;

void Delay12us(void)	//@12.000MHz
{
	unsigned char data i;

	_nop_();
	_nop_();
	i = 38;
	while (--i);
}

void wave_init()
{
  unsigned char i;
  for(i = 0;i<8;i++)
  {//发送8个方波
    TX = 1;
    Delay12us();
    TX = 0;
    Delay12us();
  }
}
unsigned int ut_wave_data()
{
  unsigned int time;
 
  CH = CL = 0;//清空PCA寄存器计数值
  CMOD = 0x00;//初始化PCA寄存器
  
  EA = 0;//关闭总中断
  wave_init();//发送方波
  EA = 1;//打开总中断
  
  CR = 1;//PCA开始计数
  while((RX == 1) && (CF == 0));//RX=1说明一直没有收到信号;CF = 0说明没有溢出
  CR = 0;//PCA停止计数
  
 if(CF == 0)
 {//如果没有溢出,则表示正常收到信号
    time = CH<<8 | CL;
    return (time*0.017);
  }
  else
  {//如果溢出,清除溢出标志位
    CF = 0;
    return 0;
  }
  
}

IIC

PCF8591

//AD:模拟(外设)(电压)->数字(计算机)

//AIN0: 右边排针 channel 0 0x00

//AIN1: 光敏电阻 channel 1 0x01

//AIN2: 放大器 channel 2 0x02

//AIN3: 滑动变阻器channel 3 0x03

u00;
  IIC_SendByte(0x91);
  IIC_WaitAck();
  
  temp = IIC_ReceiveByte();
  IIC_SendAck(1);
  IIC_Stop();
  
  return temp;
  
}
void Write_DA(unsigned char data)
{
  IIC_Start();
  IIC_SendByte(0x90);
  IIC_WaitAck();
  
  IIC_SendByte(0x41);//使能转换0x41 0x43皆可以
  IIC_WaitAck();
  
  IIC_SendByte(data);
  IIC_WaitAck();
  IIC_Stop();
}

EEPROM

AT24C02有32页,每页可以存储8个字节;如果在同一页内容超过了8个字节,则会覆盖先前的字节

//p是要写入的数据的地址   address是写入EEPROM中的地址  size 是要写入的大小
void EEPROM_Write(unsigned char *p,address,size)
{
  IIC_Start();
  IIC_SendByte(0xA0);//选择EEPROM 写模式
  IIC_WaitAck();
  
  IIC_SendByte(address);//发送要写入的地址
  IIC_WaitAck();
  
  while(size--)
  {
    IIC_SendByte(*p++);//*为解引用,即取出该地址中的内容   ++表示执行完后数组地址加一位
    IIC_WaitAck();
    IIC_Delay(200);
  }
  IIC_Stop();
}
void EEPROM_Read(unsigned char *p,address,num)
{
  IIC_Start();
  IIC_SendByte(0xA0);
  IIC_WaitAck();
  
  IIC_SendByte(addr);
  IIC_WaitAck();
  
  IIC_Start();
  IICSendByte(0xA1);
  IIC_WaitAck();
  
  While(num--)
  {
    *p++ = IICReceiveByte();
    if(num) IICSendAck(0);//如果还有数据,发送应答0
    else IIC_SendAck(1);//如果无数据,不应答
  }
  IIC_Stop();
}

串口

在<stdio.h>的头文件中,函数sprintf(uart_send,“T = %f”,T);

Sprintf 可以将一个整数或其他想添加到字符串的数添加到字符串,注意unsigned char 型的值-48后才是正常数字,亦或者将其转换为unsigned int 型,用%d占位

void Uart1_Init(void)	//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xE6;			//设置定时初始值
	T2H = 0xFF;			//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时
    ES = 1;  //打开串口中断
    EA = 1;  //打开总中断
}

void SendByte(unsigned char dat)
{
  SBUF = dat;//将数据赋给SBUF,将数据发出
  while(TI == 0);//等待数据发送
  TI = 0;//将发送标志位清零
}
void Uart_Send_String(unsigned char *dat)
{
  while(*dat != '\0')//当字符不为空是继续发送
    SendByte(*dat++);//取出data数组的第一个后接着取下一个,直到读取到\0
}

串口接受电脑数据时要记得将指针清零

void Uart_Pro()
{
  if(Uart_Slow_Down) return;
  Uart_Slow_Down = 1;
  
  if(Uart_Recv_Index > "size") //如果要发送索引大于字符串长度,清零
    Uart_Recv_Index = 0;
  
  if(Uart_Rec_Index == 1)//接收一个字符的数据
  {
    if(Uart_Rec[0] == 'a')
    {
      //执行相应操作
    }
    Uart_Rec_Index = 0;//将索引清零
  }
}
void Uart1_Routine() interrupt 4
{
  if(RI == 1 && Uart_Recv_Index < "size")// 串口接受数据
  {
    Uart_Recv[Uart_Recv_Index] = SBUF;//将SBUF区的数据赋给uart接受数组
    Uart_Recv_Index++;//数组索引++
    RI = 0;
  }
}

串口所用引脚P30 和 P31 TX = P3^1,RX = P3^0,

在使用时可能会遇到无法发送的问题,可以查看是否用到了P30,P31这两个引脚;

记得打开中断ES= 1;EA= 1;

extern char putchar(char ch)
{
  SBUF = ch;//将要发送的数据给SBUF
  while(TI == 0);//等待数据发送
  TI = 0;//将发送标志位清零
  return (ch);
}

/*发送的时候*/
printf("%d",s);//直接打印

进阶矩阵键盘

unsigned int Key_Read()
{
	unsigned int temp = 0;//16bit对应16个按键
	int row, col;
	
	for(col=0;col<4;col++) 
	{
		P44 = (col != 0);
		P42 = (col != 1);
		P35 = (col != 2);
		P34 = (col != 3);
		
		for(row=0;row<4;row++) 
		{
			if (!(P3&(0x08>>row))) //第0行-P33 第1行-P32 第2行-P31 第3行-P30 顺序相反 
				temp |= (1 << ( col* 4 + row ));
		}
	}
	return temp;
}
//main函数
#define Key_Num(i) 0x0001 << (i-4)
#define KeyDown_Num(i) Key_Down & Key_Num(i)
#define KeyUp_Num(i) Key_Up & Key_Num(i)

void Key_Proc()
{
    if(Key_Slow_Down) return;
    Key_Slow_Down = 1;

    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Old ^ Key_Val);
    Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
    Key_Old = Key_Val;

    if(KeyDown_Num(4))
    {
        if(!KeyDown_Num(9)) //排除组合按键
        {
            //S4单按键功能区
        }
    }

    if(KeyDown_Num(9)) //按键S9产生下降沿
    {
        if(!KeyDown_Num(4)) //排除组合按键
        {
            //S9单按键功能区
        }
    }

    if((KeyDown_Num(4)) && (KeyDown_Num(9))) 
    {
        //S4+S9组合按键功能区
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

l);
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
Key_Old = Key_Val;

if(KeyDown_Num(4))
{
    if(!KeyDown_Num(9)) //排除组合按键
    {
        //S4单按键功能区
    }
}

if(KeyDown_Num(9)) //按键S9产生下降沿
{
    if(!KeyDown_Num(4)) //排除组合按键
    {
        //S9单按键功能区
    }
}

if((KeyDown_Num(4)) && (KeyDown_Num(9))) 
{
    //S4+S9组合按键功能区
}

}


[外链图片转存中...(img-0Cv6uT9x-1723276501455)]

[外链图片转存中...(img-M58SmT1W-1723276501456)]



  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值