蓝桥杯之单片机学习(三十)——模板罗列、技巧总结与心得

一、模板罗列

1.1 iic.h

#ifndef __IIC_H__
#define __IIC_H__

#include <STC15F2K60S2.h>
#include "intrins.h"

sbit SD = P2^1;
sbit SCL = P2^0;

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
void Read_DAC(unsigned char date);
unsigned char Write_ADC(unsigned char add);

#endif

1.2 ds1302.h

#ifndef __DS1302_H__
#define __DS1302_H__

#include <STC15F2K60S2.h>
#include <intrins.h>

sbit SCK = P1^7;		
sbit SDA = P2^3;		
sbit RST = P1^3; 

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );

#endif

1.3 onewire.h

#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__

#include <STC15F2K60S2.h>

sbit DQ = P1^4;  

unsigned char rd_temperature(void);  

#endif

1.4 main.c

#include <STC15F2K60S2.h>
#include "onewire.h"
#include "iic.h"
#include "ds1302.h"

#define uchar unsigned char
#define uint unsigned int
	
uchar SMG_duanma[10] = {0XC0, 0XF9, 0XA4, 0XB0, 0X99, 0X92, 0X82, 0XF8, 0X80, 0X90};

uchar yi,er,san,si,wu,liu,qi,ba;

void SelectHC138(uchar channel);
void initsys();
void DisplaySMG_Bit(uchar pos, uchar value);
void Delay_one_ms_SMG();
void SMG_Display();
void Alone_Key();
void Delay_five_ms_Key();



void main()
{
	yi = er = san = si = wu = liu = qi = ba = 0;
	
	initsys();
	while(1)
	{
		Alone_Key();
		SMG_Display();
	}
}

//
void SelectHC138(uchar channel)
{
	switch(channel)
	{
		case 4:    //LED
			P2 = (P2 & 0X1F) | 0X80;
		break;
		case 5:    //蜂鸣器和继电器
			P2 = (P2 & 0X1F) | 0XA0;
		break;
		case 6:    //位码
			P2 = (P2 & 0X1F) | 0XC0;
		break;
		case 7:    //段码
			P2 = (P2 & 0X1F) | 0XE0;
		break;
	}
}

void initsys()
{
	SelectHC138(5);
	P0 = 0X00;//关闭蜂鸣器和继电器
	SelectHC138(4);
	P0 = 0XFF;
	
	SelectHC138(6);
	P0 = 0XFF;
	SelectHC138(7);
	P0 = 0XFF;
}

void DisplaySMG_Bit(uchar pos, uchar value)
{
	SelectHC138(6);
	P0 = 0X01 << pos;
	SelectHC138(7);
	P0 = value;
}

void Delay_one_ms_SMG()
{
	uint j;
	for(j = 845; j > 0; j--);
}

void SMG_Display()
{
	DisplaySMG_Bit(0, SMG_duanma[yi] & 0X80);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(1, SMG_duanma[er] - 0X80);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(2, SMG_duanma[san] | 0X80);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(3, SMG_duanma[si]);
	Delay_one_ms_SMG();
	
	DisplaySMG_Bit(4, SMG_duanma[wu]);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(5, SMG_duanma[liu]);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(6, SMG_duanma[qi]);
	Delay_one_ms_SMG();
	DisplaySMG_Bit(7, SMG_duanma[ba]);
	Delay_one_ms_SMG();
}

void Delay_five_ms_Key()
{
	uint i,j;
	for(i = 0;i < 5;i++)
		for(j = 845; j > 0;j--);
}

void Alone_Key()
{
	//S7
	if(P30 == 0)
	{
		Delay_five_ms_Key();
		if(P30 == 0)
		{
			yi = 1;
		}
		while(!P30);
	}
	//S6
	if(P31 == 0)
	{
		Delay_five_ms_Key();
		if(P31 == 0)
		{
			er = 1;
		}
		while(!P31);
	}
	//S5
	if(P32 == 0)
	{
		Delay_five_ms_Key();
		if(P32 == 0)
		{
			san = 1;
		}
		while(!P32);
	}
	//S4
	if(P33 == 0)
	{
		Delay_five_ms_Key();
		if(P33 == 0)
		{
			si = 1;
		}
		while(!P33);
	}
}

void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void Timer0Service() interrupt 1
{
	
}


1.5 onewire.c

#include "onewire.h"

//单总线内部延时函数
void Delay_OneWire(unsigned int t)  
{
	t = t * 12;
	while(t--);
}

//单总线写操作
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//单总线读操作
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

float Get_temp()
{
	float temp;
	unsigned char hig,low;
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0X88);
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0XEE);
	
	low = Read_DS18B20();
	hig = Read_DS18B20();
	temp = (hig<<8|low)*0.0625;
	return temp;
}
//temp = (int)Get_temp()
//shi = temp / 10;

1.4 iic.c

#include "iic.h"

#define DELAY_TIME 5

//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//I2C总线启动信号
void IIC_Start(void)
{
    SD = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SD = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//I2C总线停止信号
void IIC_Stop(void)
{
    SD = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SD = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答或非应答信号
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SD = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SD = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SD;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//I2C总线发送一个字节数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SD  = 1;
        else SD  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SD) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

unsigned char Write_ADC(unsigned char add)
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0X91);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return dat;
}

void Read_DAC(unsigned char date)
{
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(0X40);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	IIC_Stop();
}

void EEPROM_write(unsigned char add,unsigned char date)
{
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Delay(5);
}

unsigned char EEPROM_read(unsigned char add)
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0XA1);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return dat;
}

1.4 ds1302.c

#include "ds1302.h"  									

#define DecToBCD(dec) (dec/10*16)+(dec%10)
#define BCDToDec(BCD) (BCD/16*10)+(BCD%16)

//写字节
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

void Init_DS1302()
{
	unsigned char i,add;
	add = 0X80;
	Write_Ds1302_Byte(0X8E, 0X00);
	for(i = 0; i < 7; i++)
	{
		Write_Ds1302_Byte(add,DecToBCD(shijian[i]));
		add = add + 2;
	}
}

void Read_DS1302()
{
	unsigned char i,add;
	add = 0X81;
	for(i = 0; i < 7; i++)
	{
		shijian[i] = BCDToDec(Read_Ds1302_Byte());
		add = add + 2;
	}
	
}

二、一些技巧总结

  1. 共阳数码管,BCD数字-0X80就是带小数点,共阴就是|0X80
  2. iic和ds1302同时使用时,注意SDA的重复定义
  3. 底层逻辑代码,一定要多练
  4. iic:ADC/DAC、EEPROM
  5. onewire:温度
  6. ds1302:时钟
  7. 注意12MHz
  8. 读温度和iic,的精度,可以用float接
//ds1302用
#define DecToBCD(dec) (dec/10*16)+(dec%10) //十进制转十六进制
#define BCDToDec(BCD) (BCD/16*10)+(BCD%16) //十六进制转十进制
  1. EEPROM有7个地址,每个地址有8位

三、心得

对于蓝桥杯,回忆了好多事情,一点一点学吧,真的,只要每天学一点,就可以很厉害,博主是没有买课,各种嫖(比我同学那种买课的,我就像野路子,hhhh~),从学长那嫖的一种网课,加上B站的小蜜蜂。博主也是这样一路学过来,之后开始写省赛题,一开始有畏难心理,之后就慢慢克服了(一定要先自己独立写,一般都可以自己写出来的)。
自己的模板有了,可以用,但考试前一定要多练,多练!,一定要!还要EEPROM、DA/AD,等等小函数,考前也一定要多练!!!
对于买课呢,也挺好,是个正规路子,我同学都90-110不等,所以自己看情况吧
对于这次的比赛呢,超声波模块我是真的没想到,哈哈哈哈哈,直接放弃,别的模块都尽全力去写。
对于客观题呢,看一遍历届赛题吧,虽然感觉没多大用,但是聊胜于无吧,模电数电一定要认真学,还有官方提供的手册,博主也不知道该怎么看,哈哈哈哈,比较菜,客观题好像可以从里面找答案。
如果有时间,我说有时间的话,可以对驱动进行更深度的理解,了解原理。博主之后有时间会再看看
此次蓝桥之后,博主就准备进攻STM32了,应该再学期吧,不知道有没有时间,听说课很多。

posted @ 2022-05-14 22:17  周末不下雨  阅读(167)  评论(0编辑  收藏  举报