蓝桥杯单片机常用模块(自己整理的)

关于我写的程序啥都不是还有脸上传的事

之前一直在用txt记笔记,但是后来因为代码太多了,所以想到了记到csdn上
下面是正文,无顺序,想到哪写到哪。
这是我2021年写的一些乱七八糟的代码,现在看来真是混乱。

一些基础的

-在138译码器中,前3位代表5 6 7

P2=0xA0对应着1010 0000,则5 6 7为101,为1111 1011,Y5为0,则配置的是Y5C,控制P00-P07

P2=0x80对应着1000 0000,则5 6 7为100 为1111 0111,Y4为0,对应Y4C,这个是led灯

P2=0xC0对应着1100 0000,则5 6 7为110 为1111 1101,Y6为0,对应Y6C,这是打开数码管的片选端(控制是第几个显示),后面写P0为什么表示选哪几个,例:0x80就是1000 0000,第一个显示,也可以写为P2=(P2&0X1f)|0X80,0x80前面那个表示将P2.0-P2.4置为0

P2=0xE0对应着 1110 1111,则5 6 7位111为1111 1110,Y7为0,对应Y7C,这个是打开数码管的数据端(控制是显示什么数字)

sfr是定义特殊功能寄存器,单片机里面,共有两种寄存器,第一种是ROM,第二种是RAM。
1 ROM的功能:ROM的数据在程序运行的时候是不容改变的,除非你再次烧写程序,他就会改变,就像我们的书本,印上去就改不了了,除非再次印刷,这个就是ROM的原理。
2 RAM的功能:RAM就是在程序运行中,数据会随时改变的,就像我们的黑板,写上了可以擦,擦完再写上去,相当于程序运行的时候,调用ROM里面的数据进行各种运算。

共阳极数码管数据表:

unsigned char code shuzi[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0xbf,0xff};//0-9,第10个是-,11是全灭
unsigned char code zimu[]={0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xc1};//A,b,C,d,E,F,H,L,P,U

常用字母段码表
在这里插入图片描述

数码管片选位置表(从左到右0-7):

unsigned char code weizhi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

数码管调用函数,前面是位置,后面是显示的东西,分为shuzi和zimu两种

void shumaguan_shuzi(uchar a,uchar b)
{
	delay_ms(1);
	P2=(P2&0X1f)|0xC0;P0=weizhi[a];
	P2=(P2&0X1f)|0xE0;P0=shuzi[b];
	delay_ms(1);
	//消隐
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 0x00;
	P2 = P2 & 0x1f;
}
void shumaguan_zimu(uchar a,uchar b)
{
	delay_ms(1);
	P2=(P2&0X1f)|0xC0;P0=weizhi[a];
	P2=(P2&0X1f)|0xE0;P0=zimu[b];
	delay_ms(1);
	//消隐
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 0x00;
	P2 = P2 & 0x1f;
}

配置所有引脚

void allinit()
{
 P2=(P2&0x1f)|0x80;
 P0=0xff;
 P2&=0x1f;
 
 P2=(P2&0x1f)|0xA0;
 P0 = P0 & 0XAF; 
 P2&=0x1f;
 
 P2=(P2&0x1f)|0xc0;
 P0=0xff;
 P2&=0x1f;
 P2=(P2&0x1f)|0xe0;
 P0=0xFF;
 P2&=0x1f;
}

LED灯单独亮选择

unsigned char ledweizhi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void ledlight(uchar x)
{
	P2=(P2&0X1f)|0x80;
	P0=ledweizhi[x];
}

定时器

定时器0,设置1s:

void Init_timer0()      
{
	TMOD = 0x01;      
	TH0 = (65535 - 50000) / 256;  //50000微秒
	TL0 = (65535 - 50000) % 256;	
	EA  = 1;     
	ET0 = 1;     
	TR0 = 1;     
}

下面是以时钟为例,写执行的内容

void Service_timer0() interrupt 1
{
	TH0 = (65535 - 50000) / 256;    
	TL0 = (65535 - 50000) % 256;	
count++;
	if(count == 20)   //20*50ms为1s
	{
		second++;
		count = 0;
	}	
	if(second == 60)
	{
		minute++;
		second=0;
	}
	if(minute==60)
	{
		hour++;
		minute=0;
		if(hour==24) hour=0;
	}
	
}

矩阵按键

定义引脚

sbit R1=P3^0;//第一排初始化(如果跳线帽在右边,则只有最左侧一列可以控制,写这个没问题)
sbit R2=P3^1;//第二排初始化
sbit R3=P3^2;//第三排初始化
sbit R4=P3^3;//第四排初始化

sbit C1=P3^4;//第一列初始化(此为从右往左数)
sbit C2=P3^5;//第二列初始化
sbit C3=P4^2;//第三列初始化
sbit C4=P4^4;//第四列初始化

初始化矩阵键盘

void Init()//初始化矩阵键盘
{
	R1=R2=R3=R4=1;
	C1=C2=C3=C4=1;
}

DS18B20配置

首先是看原理图,找到DQ,连接着P14
所以先定义好DQ

sbit DQ=P1^4;
void dsinit()
{
  DQ=0;
	Delay500us();
  DQ=1;
	Delay500us();
}

温度获取:

void temperature_get()
{
	uchar high,low;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);

	
	
  	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	
	temp=((high<<4)|(low>>4));//不带小数点
	temp2=low&0x0f*100/16;//取两位小数点
	shi=temp%100/10;
	ge=temp%10;
	//int temp;uchar shi;uchar ge;int temp2;都是全局的
}

防抖

按下按键,语句只执行一次:
这里以R1为例

if(R1==0)
	{
		delay_ms(50);
		if(R1==0)
		{
			//执行语句
			while(R1==0);
		}
	}

下面是一堆delay函数

有不同时间的,应该好用,我自己试过了

void Delay100us()		//@12.000MHz
{
	unsigned char i, j;

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

void Delay500us()		//@12.000MHz
{
	unsigned char i, j;

	i = 6;
	j = 211;
	do
	{
		while (--j);
	} while (--i);
}


void delay_ms(unsigned int n)
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}

nop()的意思是一条空语句,用来延时

PCF8591

本来上课讲了,但是我一点也没听,看了这篇文章之后,就懂了,可以说是写的真好
关于iic与pcf8591

步骤:开启总线-----发送地址+写-----发送控制字节-----等待PCF8591响应-----停止总线-----重新启动总线-----发送地址+读------读取数据-----主机发送非应答信号-----停止总线

PCF8591的设备地址包括固定部分和可编程部分。可编程部分需要根据硬件引脚A0、A1和A2来设置。设备地址的最后一位用于设置数据传输的方向,即读/写位,在IIC总线协议中,设备地址是起始信号后第一个发送的字节。如果硬件地址引脚A0、A1、A2均接地,那么,PCF8591的设备的读操作地址为:0x91;而写操作地址则为:0x90。读是1,写是0

光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01。
电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。

//ADC转换,可以带入数值
unsigned char ad(unsigned int voltage)
{
	uint temp;
	uint v;
	int flag;
	IIC_Start();							
	IIC_SendByte(0x90); 	//写操作
	flag=IIC_WaitAck();  	//等待应答,判断对方发送的是0还是1,从而执行下一步
	if(flag) return 0;
	IIC_SendByte(0x40); 	
	flag=IIC_WaitAck();  		
	if(flag) return 0;
	IIC_SendByte(voltage_1); 	
	flag=IIC_WaitAck();  	
	if(flag) return 0;
	IIC_Stop(); 							

	
	IIC_Start();											
	IIC_SendByte(0x91); 	//读操作	
	flag=IIC_WaitAck();  		
	if(flag) return 0;	
	temp= IIC_RecByte();	
	
	IIC_SendAck(1); 					
	IIC_Stop();
}

读取电压,5v电压

void Read_AIN3()
{
	int voltage;
	int dat;
	IIC_Start();						
	IIC_SendByte(0x90); 	
	IIC_WaitAck();  	
	IIC_SendByte(0x03);//读取的Rb2电位器,通道三,要是0x01就是光敏电阻 	
	IIC_WaitAck();  						
	IIC_Stop(); 						
	
	IIC_Start();											
	IIC_SendByte(0x91); 			
	IIC_WaitAck(); 				
	dat = IIC_RecByte();	 			
	IIC_WaitAck(); 						
	IIC_Stop(); 						

	
	voltage=dat*100/51;
	shumaguan_shuzi(6,voltage%100/10);
	shumaguan_shuzi(7,voltage%10);
	P2=(P2&0X1f)|0xC0;P0=weizhi[5];
	P2=(P2&0X1f)|0xFF;P0=shuzi[voltage/100]+0x80;
	
}

三位数显示在数码管上:
百位:dat / 100
十位:(dat % 100) / 10
个位:dat % 10

下面是转载隔壁宿舍大佬的代码,一个函数实现ADC和DAC

void adc_read(unsigned char ain)//在ain这里写0x01和0x03使用光敏电阻和电位器
{
	EA = 0;
  	IIC_Start();								
	IIC_SendByte(0x90); 					
	if(!IIC_WaitAck()) 
	{		
	IIC_SendByte(ain); 				
	if(!IIC_WaitAck())
	{		
	IIC_Stop(); 								
	
	IIC_Start();								
	IIC_SendByte(0x91); 				
	if(!IIC_WaitAck())
	{		
	addata = IIC_RecByte(); 			
	IIC_SendAck(0);		
	vi=(addata*100)/51;
	v1=vi%1000/100;
	v2=vi%100/10;
	v3=vi%10;
	IIC_Stop();
	}
	} 
  	}
	EA = 1;
}
void dac_write(float dat)
{
	int dat_2;
	dat_2 = dat*100*255/500;
  	EA=0;
  	IIC_Start();
	IIC_SendByte(0X90);
	if(!IIC_WaitAck())
	{
	IIC_SendByte(0X40);  
	if(!IIC_WaitAck())
	{
	IIC_SendByte(dat_2);
  if(!IIC_WaitAck())	
	{
	IIC_Stop();
	}
  	}
	}
	EA=1;
}

读写eeprom的函数

在write_eeprom和read_eeprom时一定要中间写一个delay,要不然数据读不进去

void write_eeprom(unsigned char add,unsigned char date)//写入eeprom数据,前面是地址,后面是数据
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	IIC_Stop();
}
unsigned char read_eeprom(unsigned char add)//读eeprom的数据,括号里面写地址
{
	unsigned char temp;
	EA = 0;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_WaitAck();
	IIC_Stop();
	EA = 1;
	return temp;
}

NE555

unsigned int count_f = 0;
unsigned char count_t = 0;
unsigned int dat_f = 0;
void Init_Timer()
{
	TH0 = 0xff;        
	TL0 = 0xff;
	
	TH1 = (65536 - 50000) / 256;        
	TL1 = (65536 - 50000) % 256;
	TMOD = 0x16;     
  	ET0 = 1;
  	ET1 = 1;
	EA = 1;
	TR0 = 1;
	TR1 = 1;
}
 
void Service_T0() interrupt 1
{
	count_f++;
}
 
void Service_T1() interrupt 3
{
  TH1 = (65536 - 50000) / 256;        
	TL1 = (65536 - 50000) % 256;
	count_t++;
	if(count_t == 20)
	{
		dat_f = count_f;
		count_f = 0;
		count_t = 0;
	}
}
void display_f()
{
	
	shumaguan_zimu(0,5);
	if(dat_f>9999)
		shumaguan_shuzi(3,dat_f/10000);
	if(dat_f>999)
		shumaguan_shuzi(4,dat_f/1000%10);
	if(dat_f>99)
		shumaguan_shuzi(5,dat_f/100%10);
	if(dat_f>9)
		shumaguan_shuzi(6,dat_f/10%10);
		
		shumaguan_shuzi(7,dat_f%10);
	
}

以1s间隔闪烁一次,以第八届省赛的题目为例,要求每隔1s闪烁一次

void Init_timer0()//定时器配置      
{
	TMOD = 0x01;      
	TH0 = (65535 - 50000) / 256; //50ms技术   
	TL0 = (65535 - 50000) % 256;	
	EA  = 1;     
	ET0 = 1;     
	TR0 = 1;     
}
void Service_timer0() interrupt 1//定时器0,中断
{
		count_b++;//全局变量
	if(count_b==20)//计算了1s
	{
		count_b=0;
		if(mode_smg==0)//mode_smg也是全局变量
		{
			mode_smg=1;
		}
		else if(mode_smg==1)
		{
			mode_smg=0;
		}
	}
}
void hour_blink()//显示小时以1s的间隔显示一次
{
	if(mode_smg==1)
		{
			shumaguan_shuzi(0,hour_p/10);
			shumaguan_shuzi(1,hour_p%10);
			shumaguan_shuzi(2,10);
			shumaguan_shuzi(3,minute_p/10);
			shumaguan_shuzi(4,minute_p%10);
			shumaguan_shuzi(5,10);
			shumaguan_shuzi(6,second_p/10);
			shumaguan_shuzi(7,second_p%10);
		}
		if(mode_smg==0)
		{
			shumaguan_shuzi(0,11);
			shumaguan_shuzi(1,11);
			shumaguan_shuzi(2,10);
			shumaguan_shuzi(3,minute_p/10);
			shumaguan_shuzi(4,minute_p%10);
			shumaguan_shuzi(5,10);
			shumaguan_shuzi(6,second_p/10);
			shumaguan_shuzi(7,second_p%10);
		}
}

先写这么多,想到了继续补

  • 14
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sol-itude

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值