【第十四届蓝桥杯单片机组底层驱动测试】

2023-11-16

【第十四届蓝桥杯单片机组底层驱动测试】

下面分享的是第十四届蓝桥杯单片机组底层驱动代码的测试和相关说明,今年官方提供的资料包中底层驱动代码和以往有了变化,主要代码还是提供给了我们,只是此次没有了相关头文件iic.h ds1302 onewire.h,这三个文件需要我们自行添加,其次就是整个驱动的改动,下面将具体介绍。

完整工程和底层驱动文件有需要的自取哈
链接:https://pan.baidu.com/s/1yAfgSQ0ohivGgZngeYeqsw?pwd=3ub8 
提取码:3ub8 
--来自百度网盘超级会员V5的分享

有帮助就给博主一个关注和点赞吧,祝大家都可以取得好成绩哦
在这里插入图片描述

iic.c

在IIC.C文件我们除了要加上iic.h头文件,还需修改I2C_Delay函数,在该函数中只需保留一个_nop_()函数就行,多余的_nop_()函数删除掉,还要注意_nop_()函数头文件intrins.h的包含,另外IIC相关的SCL和SDA的引脚定义需要我们自己记住,在提供的资料包中并没有改引脚的定义,当然到时候也可以查看原理图,最好可以记住吧具体见iic.h。

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"       

#define DELAY_TIME	5

//
void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

iic.h

在iic.h头文件 注意将各个函数的声明添加到这里哦,以及相关的头文件和引脚定义

#ifndef _IIC_H_
#define _IIC_H_

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

sbit sda = P2^1;
sbit scl = P2^0;
void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CSendByte(unsigned char byt);
void I2CStop(void);
unsigned char I2CWaitAck(void);
unsigned char I2CReceiveByte(void);
void I2CSendAck(unsigned char ackbit);

#endif

ds1302.c

在ds1302.c头文件中只需添加ds1302.h就好,其他函数中没有需要更改中,其余相关声明和引脚定义在ds1302.h中包含就好了

/*	# 	DS1302代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/								

#include "ds1302.h"

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

//
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; 
}

//
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);			
}

ds1302.h

在ds1302中同样没有提供引脚定义也需要我们自己记住哦

#ifndef _DS1302_H_
#define _DS1302_H_

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

sbit RST = P1^3;
sbit SCK = P1^7;
sbit SDA = P2^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

onewire.c

onewire.c中相对以往的Delay_OneWire函数 这里进行了12倍的处理,就不需要我们自己改动了,只需添加onewire.h头文件就好,其他相关在onewire.h中包含

/*	# 	单总线代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "onewire.h"
//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

//
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;
}

//
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;
}

onewire.h

注意温度的引脚P1^4 IO口哦,将相关函数声明添加到onewire.h头文件中,delay_onewire函数的static可去可不去都行

#ifndef _ONEWIRE_H_
#define _ONEWIRE_H_

#include <STC15F2K60S2.H>

sbit DQ = P1^4;
void Delay_OneWire(unsigned int t) ;
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif

以上就行三个驱动文件的讲解啦,下面以按键4 分别进行三个功能的切换显示,并且每个界面的切换伴随LED亮灭的切换

#include <STC15F2K60S2.H>
#include "iic.h"
#include "onewire.h"
#include "ds1302.h"
/*=========================================十四届蓝桥杯单片机底层驱动测试================================
@Author:小殷
@Date:2023.4.2
======================================================================================================*/
typedef unsigned char uchar;
typedef unsigned int  uint;
#define Control_Port(x,y) P0 = y;P2 = x;P2 = 0
uchar  smg_bit[9] = {10,10,10,10,10,10,10,10,10};            //设置为10对应着0xff 关闭数码管初始化
//数码管段码 0-9 shut-off -
uchar  smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff, 0xbf,0xc1,0x86};
uchar key_feq = 0,t_feq = 0,adc_feq = 0;   //按键 温度 adc采集刷新频率
uchar interface = 1;                       //界面
uchar hour = 0,min = 0,sec = 0;            //时分秒
uint adc_volt = 0,Temperature = 0;         //adc电压 温度
uchar L[4];                                //LED控制

//==========================================下面为函数声明=================================================
void Timer2Init(void);                                  //定时器2初始化
void Set_Timer(uchar hour,uchar min,uchar sec);         //DS1302时间设置
uchar Read_ADC_Value(uchar addr);                       //ADC获取
uchar Read_Temperature_Value(void);                     //读取温度
uchar Read_Key_Value(void);                             //读取按键值
void Data_Tackle_Task(void);                            //数据处理
void SMG_Display_Task(void);                            //数码管显示
void Key_Tackle_Task(void);                             //按键处理
void Init_System(void);                                 //系统初始化
//==========================================下面为函实现===================================================
void Timer2Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x20;		//设置定时初始值
	T2H = 0xD1;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时
	IE2 |= 0x04;
	EA = 1;
}


void Set_Timer(uchar hour,uchar min,uchar sec)
{
	Write_Ds1302_Byte(0x8e,0x00);               //关闭写保护
	Write_Ds1302_Byte(0x80,sec/10*16 + sec%10); //BCD码
	Write_Ds1302_Byte(0x82,min/10*16 + min%10); //BCD码
	Write_Ds1302_Byte(0x84,hour/10*16 +hour%10);//BCD码
	Write_Ds1302_Byte(0x8e,0x80);               //打开写保护
}

uchar Read_ADC_Value(uchar addr)
{
	uchar adc = 0;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	adc = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return adc;
}

uchar Read_Temperature_Value(void)
{
	uchar LSB = 0,MSB = 0;
	uint temp = 0;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	temp = (MSB << 8 | LSB);
	temp = temp * 0.0625 * 10; //扩大十倍方便显示
	return temp;
}


uchar Read_Key_Value(void)
{
	static uchar last_trg = 0,cnt = 0;
	uchar trg = 0,cur = 0,value = 3;
	
	cur = (P3|0x10)^0xff;
	trg = cur^cnt&cur;
	cnt = cur;
	if((last_trg ^ trg & last_trg) && cur)
	{
		if(cur & 0x08) value = 4;
		else if(cur & 0x04) value = 5;
		else if(cur & 0x02) value = 6;
		else if(cur & 0x01) value = 7;
	}
	last_trg = trg;
	return value;
}

void Data_Tackle_Task(void)
{
	uchar time[3];
	if(T2H < 0xd9)
	{
		time[0] = Read_Ds1302_Byte(0x81);
		time[1] = Read_Ds1302_Byte(0x83);
		time[2] = Read_Ds1302_Byte(0x85);
		
		hour = (time[2]/16*10 + time[2]%16);
		min  = (time[1]/16*10 + time[1]%16);
		sec  = (time[0]/16*10 + time[0]%16);
		
	}
	if(adc_feq > 150)
	{
		adc_feq = 1;
		adc_volt = Read_ADC_Value(0x03) * (5.0/255) * 100;
	}
	
	if(t_feq > 120)
	{
		t_feq = 1;
		Temperature = Read_Temperature_Value();
	}
	
	
	//LED逻辑控制
	L[1] = (interface == 1)?(1):(0);
	L[2] = (interface == 2)?(1):(0);
	L[3] = (interface == 3)?(1):(0);
}

void SMG_Display_Task(void)
{
	if(interface == 1)
	{
		smg_bit[1] = 12;       //U
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = adc_volt/100;
		smg_bit[7] = adc_volt/10%10;
		smg_bit[8] = adc_volt%10;
	}
	else if(interface == 2)
	{
		smg_bit[1] = 13;       //E  0110 0001  0x86
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = Temperature/100;
		smg_bit[7] = Temperature/10%10;
		smg_bit[8] = Temperature%10;
	}
	else if(interface == 3)
	{
		smg_bit[1] = hour/10;      
		smg_bit[2] = hour%10;
		smg_bit[3] = 11;
		smg_bit[4] = min/10;
		smg_bit[5] = min%10;
		smg_bit[6] = 11;
		smg_bit[7] = sec/10;
		smg_bit[8] = sec%10;
	}
}

void Key_Tackle_Task(void)
{
	uchar key_value = 0;
	if(key_feq > 10)
	{
		key_feq = 1;
		key_value = Read_Key_Value();
	}
	switch(key_value)
	{
		case 4:
			if(interface == 1)
			{
				interface = 2;
			}
			else if(interface == 2)
			{
				interface = 3;
			}
			else if(interface == 3)
			{
				interface = 1;
			}
			break;
		case 5:break;
		case 6:break;
		case 7:break;
		default:break;
	}
	
}

void Init_System(void)
{
	Control_Port(0x80,0xff);
	Control_Port(0xa0,0x00);
	Control_Port(0xc0,0x00);
	Timer2Init();
	Set_Timer(23,59,50);
}

void main(void)
{
	Init_System();
	while(1)
	{
		Data_Tackle_Task();
		SMG_Display_Task();
		Key_Tackle_Task();
	}
}


void Timer2_Server() interrupt 12
{
	static uchar dsp_smg = 1;
	
	Control_Port(0x80,~(L[1] << 0 | L[2] << 1| L[3] << 2));
	Control_Port(0xc0,0x00);
	if(interface == 1 && dsp_smg == 6 || interface == 2 &&dsp_smg == 7)
	{
		Control_Port(0xe0,smg_data[smg_bit[dsp_smg]] & 0x7f);
	}
	else
	{
		Control_Port(0xe0,smg_data[smg_bit[dsp_smg]]);
	}
	
	Control_Port(0xc0,1 << (dsp_smg - 1));
	if(++dsp_smg > 8)
	{
		dsp_smg = 1;
	}
	key_feq++;
	t_feq++;
	adc_feq++;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【第十四届蓝桥杯单片机组底层驱动测试】 的相关文章

  • ISO/IEC技术标准-RFID

    ISO IEC技术标准规定了RFID有关技术特征 技术参数和技术规范 主要包括ISO IEC 18000 空中接口参数 ISO IEC 10536 密耦合 非接触集成电路卡 ISO IEC 15693 疏耦合 非接触集成电路卡 和ISO I
  • html框架-----标签(上)

    目录 前言 标签简介 1 HTML的基本结构 1 html标签 2 head标签 3 body标签 2 标题标签 3 段落标签 4 文本格式化标签 前言 现在学前端工程师的都很难找工作 懂的都懂了 因为学前端一般去做那些页面可视化处理 而学
  • 微信红包实现原理

    微信红包实现原理 以下内容来源于QCon某高可用架构群聊天记录整理 背景 有某个朋友咨询微信红包的架构 在官方或非官方同学的解释和讨论中得出以下讨论内容 在此期间有多个同学发红包做现网算法测试 抢红包过程 当有人在群里发了一个N人的红包 总

随机推荐

  • js 正则替换隐藏部分身份证或手机号以及隐藏部分名字

    1 手机号隐藏中间4位 var phone 18200002111 phone replace d 3 d d 4 1 2 输出结果 2 身份证隐藏中间数字 2 1兼容尾数后面携带字母的 隐藏身份证中间8位数 param data 传入数据
  • opengles3.0_win10

    前部分的配置主要参考 https blog csdn net mmy545237835 article details 80762150 但是还会出现一系列问题 需要把下载的模拟器文件夹中的 一个文件夹和两个动态链接库放到当前的工程目录下
  • 自动化输出带数据的文件名称

    背景说明 为实现数据统计 输出文件名称中带变化的数据名称 可以进行向量变化的输出 程序说明如下 library readxl library sqldf library openxlsx library dplyr length iris
  • Kubernetes入门Day2 ~ 一步一步手工构建metrics-server 0.5.0 镜像

    i m not only a DBA k8 gcr io异步同步工具配置 一步一步编辑metrics server 0 5 0镜像 1 配置好jq 2 clone 官方metrics server 3 编辑metrics server 0
  • 软件工程和计算机科学与技术的区别在哪?

    计科专业毕业已经从事软件开发多年 说到当初选择这个专业还是遵从父母的意愿 老人家们觉得计算机是个未来的趋势 如果做个计算机的老师岂不是很不错 于是在报考志愿的时候就给选择上了 主要自身也对计算机感兴趣 所以也没有过多的干预 至于学到之后当不
  • 网络技术期末复习~重点考题

    解题思路 标准答案 11 如图所示 网络145 13 0 0 16划分为四个子网N1 N2 N3 N4 它们与路由器R相连的接口分别是m0 m1 m2 m3 R的第五个接口m4连接到互联网路由器 接口地址为1 1 1 1 1 请给出路由器R
  • uniapp 基础知识学习

    uniapp 基础知识学习 uniapp 基础知识学习 uniapp 介绍 https uniapp dcloud io README 有哪些uni app的作品 uni app的社区规模 为什么要去学习uni app 快速体验 功能框架
  • js显示服务器路径下的图片,JS处理文件流(如果是图片,显示在当前页面)

    用ajax请求图片资源 服务器以文件流的形式返回 1 返回类型需要设置为 blob 所以需要用原生ajax 不能使用jq 原因 jquery将返回的数据转换为了string 不支持blob类型 当然 你也可以引入组件拓展jq的能力 我知道的
  • leetcode----121.买卖股票的最佳时机

    给定一个数组 它的第 i 个元素是一支给定股票第 i 天的价格 如果你最多只允许完成一笔交易 即买入和卖出一支股票一次 设计一个算法来计算你所能获取的最大利润 注意 你不能在买入股票前卖出股票 示例 1 输入 7 1 5 3 6 4 输出
  • 电脑快捷键大全表格_【Mac新手必看基础篇】Mac电脑快捷键大全

    Mac电脑以卓越的性能和出色的外表获得了越来越多的用户 你是Mac新手吗 你是否能熟练使用Mac电脑呢 刚接触Mac电脑的小伙伴千万不要错过这篇文章 小编给大家准备了Mac使用必看基础篇 Mac快捷键大全 对于新手用户很有帮助哦 一 开机相
  • Git如何合并分支到主干及合并主干到分支

    Git如何合并分支到主干及合并主干到分支 文章目录 Git如何合并分支到主干及合并主干到分支 零 预备知识 一 创建分支 二 合并分支到主干 三 合并主干到分支 参考资料 精益开发实践用看板管理大型项目 Git如何合并分支到主干及合并主干到
  • 合并两个有序数组(超详细)

    合并两个有序数组 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2 另有两个整数 m 和 n 分别表示 nums1 和 nums2 中的元素数目 请你 合并 nums2 到 nums1 中 使合并后的数组同样按 非递减顺序
  • 一文读懂毫米波/激光/超声波雷达的区别(转)

    不知何时 自动驾驶技术从电影中跳出来 直接被拉到人们视野中 不过 去年特斯拉却因为几起自动驾驶事故 官网不得不把自动驾驶字眼改为辅助驾驶 本期 汽车总动员 讨论的不是自动驾驶 而是被称为自动驾驶汽车 眼睛 的雷达 目前主流的 眼睛 有四类
  • 在ubuntu下编译opencv程序后,执行报下面到错误: error while loading shared libraries: libopencv_core.so.2.4: cannot op

    转自 https www douban com note 327349156 在ubuntu下编译opencv程序后 执行报下面到错误 error while loading shared libraries libopencv core
  • 使用Python 进行分析

    在当今竞争激烈的互联网时代 对于网站的SEO优化至关重要 本文将介绍一种强大的秘密武器 使用Python 进行竞争对手网站分析 通过这种技术 您可以深入了解竞争对手的网站结构 关键词排名和优化策略 为您的SEO优化工作提供有力支持 1 为什
  • 神经网络随手记-1

    目录 sigmod函数主要缺点 Relu 线性整流函数 Leaky ReLU 随机梯度下降法 sigmod函数主要缺点 在输入值变大时 梯度会变得非常小甚至消失 这意味着 在训练神经网络时 如果发生这种饱和 我们将无法根据梯度来更新权重 函
  • 传感器尺寸与像素密度对相片分辨率的影响

    在人们日常生活摄影中 相机的传感器尺寸以及像素素往往决定了一幅图像的清晰度 当然 不同的镜头 不同的CMOS质量等等都会对相片的质量产生影响 今天就简单讨论讨论传感器尺寸和像素密度对图像分辨率的影响 当传感器尺寸一定时 像素越多 也就是像素
  • Python-集合

    探索Python集合的奇妙世界 在Python编程中 集合 Set 是一种强大且有用的数据结构 它用于存储多个不重复的元素 集合的独特之处在于它的元素是无序的 并且每个元素都是唯一的 这使得集合在处理去重和进行快速成员检查时非常有效 创建集
  • 手把手带你打造自己的UI样式库(第五章)之常用页面切图的设计与开发

    常用页面切图的设计与开发 在一些大的前端团队中 前端工程师这个职位会出现一个分支 叫做重构工程师 重构工程师主要负责 HTML 和 CSS 的制作 也就是把设计稿转换成 HTML 和 CSS 代码 重构工作完成以后 把制作好的 HTML 和
  • 【第十四届蓝桥杯单片机组底层驱动测试】

    第十四届蓝桥杯单片机组底层驱动测试 下面分享的是第十四届蓝桥杯单片机组底层驱动代码的测试和相关说明 今年官方提供的资料包中底层驱动代码和以往有了变化 主要代码还是提供给了我们 只是此次没有了相关头文件iic h ds1302 onewire