[实训] 实验1-SPI数据传输基础实验(上)

news2024/12/28 9:27:51

目  录​​​​​​​

一、实验目的

二、实验仪器及器件

三、实验内容及原理

四、实验步骤​​​​​​​

五、实验测试数据表格记录

六、实验数据分析及处理

七、实验结论与感悟


一、实验目的

使用FPGA/ARM实现SPI数据传输实验;实现数据传输程序的编写、下载、传输验证、传输波形测量,发送的数据及其数据传送过程须通过示波器测量波形验证正确性。

基本要求:

1、掌握SPI数据传输的理论基础;

2、掌握数据传输程序的编写方法;

3、掌握数据传输程序的下载与验证方法;

4、掌握示波器测量波形的正确方法;

5、掌握示波器波形的分析方法。

二、实验仪器及器件

  1. 电脑(Windows 10)
  2. PSI-STP-ST-STM32F103实验箱(ARM)
  3. 示波器

三、实验内容及原理

实验内容:基于SPIDS1302实时时钟显示实验

使用ARM实验箱实现SPI数据传输实验;实现数据传输程序的编写、仿真、下载、传输验证;传输波形测量,发送的数据及其数据传送过程须通过示波器测量波形验证正确性。

说明:DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、星期、日、月和年。

   要求:

  (1)实现DS1302控制输出时钟,并将其用数码管显示时钟时间,精确到秒;

  (2)掌握示波器测量方法,利用示波器测量波形,要求测量出SPI控制时序图。

图3.1  STM32F103实验箱

实验原理:

DS1302 是美国 DALLAS 公司推出的一种高性能、低功耗的实时时钟芯片,附加 31 字节静态 RAM,采用 SPI 三线接口与 CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和 RAM 数据。实时时钟可提供秒、分、时、星期、日、月和年,一个月小与 31 天时可以自动调整,且具有闰年补偿功能。工作电压宽达 2.5~5.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。DS1302 的外部引脚分配如下图所示。DS1302 用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。

图3.2  DS1302引脚图

四、实验步骤

  1. 建立工程,新建文件夹命名为“基于SPI的DS1302实时时钟显示实验”,核心处理器芯片是 STM32F103ZC。
  2. 添加库文件,在工程文件夹中新建 4 个文件夹为 CORE、OBJ、STM32F10X_FELIB,SYSTEM,并在官方固件库包中相关的库包复制进去。

     

    图4.1  工程目录浏览

  3. 配置工程。
  4. 编写相关程序。

  5. 编译程序,如果有报错,逐错修改直至没有错误。
  6. 在线下载调试,代码烧写完成后按下复位键(RESET),可以看到数码管从初始化好的时钟时间,精确到秒显示(初始化时间为2023年5月1日19点59分49秒,星期一):

 

图4.4  实验现象数码管显示时钟(21时12分05秒)

        7.利用示波器测量波形,测量出SPI控制时序图。

 

图4.5  试验箱DS1302@SPI

                a.时钟数据的读写地址

图4.2  时钟数据的读写地址

如上图,为DS1302芯片的时钟数据的读和写的地址,也就是说要实现对芯片控制,就是往这些地址上写入或读出数据。其中:

读地址为0x81(秒), 0x83(分), 0x85(时), 0x87(日), 0x89(月), 0x8b(星期), 0x8d(年);

写地址为0x80(秒), 0x82(分), 0x84(时), 0x86(日), 0x88(月), 0x8a(星期), 0x8c(年)。

DS1302控制软件最基本的操作为写函数和读函数,其次就是实现初始化函数

读写时序

 

图 单字节读操作时序图

 

图  单字节写操作时序图

 ds1302.c关键代码段1:读取一个地址的数据

// 从ds1302的内部寄存器addr读出一个值,作为返回值
u8 DS1302_Read_Byte(u8 addr)
{
  u8 i,temp;
	DS1302_RST = 0;         //停止DS1302总线
	delay_us(10);
	DS1302_RST = 1;         //启动DS1302总线                        
	addr = addr | 0x01;    //读数据
	DS1302_IO_OUT();  
	for(i = 0; i < 8; i ++)  //写地址
	{
	  if (addr & 0x01)          // 从低位开始传输的
			DS1302_DATA_OUT = 1;
		else
			DS1302_DATA_OUT = 0;		
		DS1302_SCK = 1;          
		delay_us(10);           
		DS1302_SCK = 0;          
    delay_us(10);
		addr = addr>>1;           // 把addr右移一位
	}
	DS1302_IO_IN();
	for (i = 0; i < 8; i ++) //读数据
	{
	  temp = temp >> 1;
		if(DS1302_DATA_IN)   // 读出来的数值是低位在前的
			temp |= 0x80;
		else
			temp &= 0x7F;	
		DS1302_SCK = 1;
		delay_us(10);
		DS1302_SCK = 0; 
    delay_us(10);
	}  
	DS1302_RST = 0;         // RST拉低意味着一个大周期的结束
	return temp;
}

ds1302.c关键代码段2:向DS1302命令(地址+数据)

//向DS1302写入一个字节数据
void DS1302_Write_Byte(u8 addr, u8 data)
{
  u8 i;
	DS1302_RST = 0;      //停止DS1302总线
	delay_us(10);
	DS1302_RST = 1;      //启动DS1302总线
	addr = addr & 0xFE;  
	DS1302_IO_OUT();
  //写地址addr
	for(i = 0; i < 8; i ++)  
	{
	  if (addr & 0x01)        // 从低位开始传输的
			DS1302_DATA_OUT = 1;
		else
			DS1302_DATA_OUT = 0;		
		DS1302_SCK = 1;         // 制造上升沿
		delay_us(10); 
		DS1302_SCK = 0;         // 把SCLK拉低
    delay_us(10); 
		addr = addr>>1;         // 把addr右移一位
	}
  	// 写数据data
	for (i = 0; i < 8; i ++) 
	{
	  if(data & 0x01)         //SPI是从低位开始传输的
			DS1302_DATA_OUT = 1;
		else
			DS1302_DATA_OUT = 0;
		
		DS1302_SCK = 1;          // 制造上升沿
		delay_us(10);            
		DS1302_SCK = 0;          
    delay_us(10); 
	  data = data>>1;          // 把addr右移一位
	}
	DS1302_RST = 0;             // RST拉低
}

ds1302.c关键代码段3:初始化时钟

//初始时间         20  23年 5月  1日  19点 59分49秒,星期1
u8 time_buf[8] = {0x20,0x23,0x05,0x01,0x11,0x08,0x56,0x01}; 
//向DS1302写入时间数据
void DS1302_Write_Time(void)
{
  DS1302_Write_Byte(ds1302_control_add, 0x00);      //关闭写保护
//  DS1302_Write_Byte(ds1302_sec_add, 0x80);          //暂停时钟
	//DS1302_Write_Byte(ds1302_charger_add, 0xA9);      //涓流充电
	DS1302_Write_Byte(ds1302_year_add,time_buf[1]);		//年 
	DS1302_Write_Byte(ds1302_month_add,time_buf[2]);	//月 
	DS1302_Write_Byte(ds1302_date_add,time_buf[3]);		//日 
	DS1302_Write_Byte(ds1302_hr_add,time_buf[4]);		  //时 
	DS1302_Write_Byte(ds1302_min_add,time_buf[5]);		//分
	DS1302_Write_Byte(ds1302_sec_add,time_buf[6]);		//秒
	DS1302_Write_Byte(ds1302_day_add,time_buf[7]);		//周 
	DS1302_Write_Byte(ds1302_control_add,0x80);		    //打开写保护 
}

 seg.c关键代码段:

void show(u8 pl)
{
  BitAction sum[8];
  u8 i;
  for(i=0;i<8;i++)
  {
  	if((data[pl]>>i)&0x01 == 0x1)	
			sum[i] = Bit_SET;
		else	
			sum[i] = Bit_RESET;
  }
  GPIO_WriteBit(GPIOG,GPIO_Pin_8,sum[7]);
  GPIO_WriteBit(GPIOC,GPIO_Pin_6,sum[6]);
  GPIO_WriteBit(GPIOC,GPIO_Pin_7,sum[5]);
  GPIO_WriteBit(GPIOA,GPIO_Pin_8,sum[4]);
  GPIO_WriteBit(GPIOG,GPIO_Pin_4,sum[3]);
  GPIO_WriteBit(GPIOG,GPIO_Pin_5,sum[2]);
  GPIO_WriteBit(GPIOG,GPIO_Pin_6,sum[1]);
  GPIO_WriteBit(GPIOG,GPIO_Pin_7,sum[0]);
}

main.c关键代码

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "12864.h"
#include "ds1302.h"
#include "seg.h"

u8 time[15];

int main(void)
{
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	DS1302_Init();
	delay_ms(10);
	DS1302_Write_Time();
  delay_ms(10);	
	Geg_GPIO_Configuration();
	while(1) 
	{
		//DS1302_Get_Time(time);
    show(time[9]);//时
    GPIO_SetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
    delay_ms(1);
    
    show(time[10]);//时
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_SetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
    delay_ms(1);
    
    show_x();//-
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_SetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
    
    show(time[11]);//min
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_SetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
    
    show(time[12]);//min
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_SetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
    
    show_x();//-
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_SetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
    
    show(time[13]);//s
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_SetBits(GPIOE,GPIO_Pin_10);
		GPIO_ResetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
    
    show(time[14]);//s
		GPIO_ResetBits(GPIOF,GPIO_Pin_13);
    GPIO_ResetBits(GPIOG,GPIO_Pin_0);
    GPIO_ResetBits(GPIOE,GPIO_Pin_9); 
		GPIO_ResetBits(GPIOF,GPIO_Pin_12);
		GPIO_ResetBits(GPIOE,GPIO_Pin_8);
		GPIO_ResetBits(GPIOE,GPIO_Pin_7);
		GPIO_ResetBits(GPIOE,GPIO_Pin_10);
		GPIO_SetBits(GPIOF,GPIO_Pin_11);
		delay_ms(1);
	}	
}

 由于篇幅原因,五、六、七见下篇

五、实验测试数据表格记录

六、实验数据分析及处理

七、实验结论与感悟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/484797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【项目原理】多点触摸屏驱动原理

一、屏幕介绍 ATK-7016 这款屏幕其实是由 TFT LCD触摸屏组合起来的。底下是 LCD 面板&#xff0c;上面是触摸面板&#xff0c;将两个封装到一起就成了带有触摸屏的 LCD 屏幕。电容触摸屏也是需要一个驱动 IC的&#xff0c;驱动 IC 一般会提供一个 I2C 接口给主控制器&#xff…

[实训] 实验1-SPI数据传输基础实验(下)

目录 五、实验测试数据表格记录 六、实验数据分析及处理 七、实验结论与感悟 五、实验测试数据表格记录 实验现象数码管显示见第四节图4.4&#xff0c;示波器测量结果见下列图片。 图5.1 RST、MOSI/MISO波形测量结果 图5.2 SCLK、MOSI/MISO波形测量结果 仅调整示波器波…

C生万物 | 剖析函数指针经典应用 —— 回调函数

不懂函数指针的老铁可以先看看这篇文章【指针函数与函数指针】&#xff0c;上车&#xff0c;准备出发&#x1f697; 文章目录 一、回调函数的概念二、为什么要使用回调函数&#xff1f;三、回调函数使用场景场景一&#xff1a;模拟计算器的加减乘除场景二&#xff1a;模拟qsort…

MySQL集群方案总结与方案原理

前言 在给自己做着玩的一个项目准备数据库集群&#xff0c;顺带自己大致系统复习并记录一下。 单节点mysql存在的常见问题 当数据量和并发量上去后&#xff0c;单节点数据库无法满足大并发时性能上的要求。单节点的MySQL无法满足高可用&#xff0c;数据库宕机或者意外中断等故障…

数据结构学习分享之双向链表详解

数据结构第四课 1.前言2. 结构分析3. 双链表的实现3.1 初始化结构3.2 初始化函数3.3 尾插函数3.4 尾删函数3.5 头插函数3.6 头删函数3.7 销毁链表3.8 其他函数 4. 缓存利用率5. 总结 1.前言 &#x1f493;博主CSDN:杭电码农-NEO&#x1f493;&#x1f389;&#x1f389;&#x…

Python(一) 基础二(语句、文件读写)

1.语句 1.1.if…elif…else 类似于java的if…else if…else语句 1.1.1.判断条件 比较运算符: 、>、<、<、>、!、is、is not、in、not in 1.1.2.和is的区别 list_1 [aaa, bbb] list_2 [aaa, bbb] print(list_1 list_2) #结果:True print(list_1 is list_2)…

async await

async await async await 都是修饰符&#xff0c;修饰函数的。 async/await一定是成对出现的。比如用async也没有什么太大意义。只要函数体中出现了await&#xff0c;则当前函数必须用async来修饰。 用async修饰的函数&#xff0c;相当于用promise包裹起来。其实相当于把同步修…

基于jeecgboot的OA日程安排开发(一)

日程安排也是OA里的一项重要功能&#xff0c;所以基于jeecgboot开发这个日程安排。 日程安排主要涉及以下几个方面&#xff1a; 1、数据库方面&#xff0c;主要是分日历与日程 日历可以分个人日历与工作日历&#xff0c;一般情况下&#xff0c;个人日历只给自己查看&#xff0…

2023-05-02 动态规划简介

动态规划简介 1 动态规划的基本概念 阶段、状态、决策、策略、状态转移方程 1) 阶段和阶段变量 将问题的全过程恰当地分成若干个相互联系的阶段闫氏DP分析法&#xff1a;对应f[i][j]的ij遍历时形成的所有f[i][j]阶段的划分一般根据时间和空间的自然特征去划分阶段的划分便于把…

Nginx原理解析

master和worker 当linux启动的时候&#xff0c;会有两个和nginx相关的进程&#xff0c;一个是master,一个是worker。 master如何工作 当客户端发送请求到nginx之后&#xff0c;master会接收到这个请求&#xff0c;然后通知所有的worker进程&#xff0c;此时&#xff0c;work…

【STL十六】函数对象:包装器(std::function)——绑定器(std::bind)——函数适配器

【STL十六】函数对象&#xff1a;包装器(std::function&#xff09;——绑定器&#xff08;std::bind&#xff09;——函数适配器 一、包装器(std::function&#xff09;1、简介2、头文件3、构造函数4、demo5、异常 二、绑定器&#xff08;std::bind&#xff09;1、简介2、头文…

Nessus漏洞扫描以及OpenSSH漏洞修复验证

主机IP地址资源kali192.168.200.1285GB内存/4CPUCentOS7.5192.168.200.1292GB内存/2CPU https://www.tenable.com/downloads/nessus?loginAttemptedtrue curl --request GET \--url https://www.tenable.com/downloads/api/v2/pages/nessus/files/Nessus-10.5.1-ubuntu1404_am…

云原生Istio案例实战

目录 1 Istio监控功能1.1 prometheus和grafana1.2 访问prometheus1.3 访问grafana 2 项目案例&#xff1a;bookinfo2.1 理解什么是bookinfo2.2 sidecar自动注入到微服务2.3 启动bookinfo2.4 通过ingress方式访问2.5 通过istio的ingressgateway访问2.5.1 确定 Ingress 的 IP 和端…

计算机视觉--图像拼接

图像拼接 单应性变换仿射变换图像扭曲实现图像嵌入&#xff08;图中图&#xff09; RANSAC算法算法介绍图片收集无RANSAC优化和有RANSAC优化的代码实现差别 总结 单应性变换 单应性变换是指一个平面上的点通过一个矩阵变换映射到另一个平面上的点&#xff0c;这个变换矩阵是一…

java聊天室的设计与实现代码

聊天室是一个简单的通信应用&#xff0c;可以帮助您与客户和朋友保持联系&#xff0c;并且可以让您更轻松地与其他员工联系。然而&#xff0c;您将不得不确保每个人都知道他们正在做什么。 一旦聊天室开始&#xff0c;它就会变得非常复杂&#xff0c;因为有许多用户可能会同时登…

【三十天精通Vue 3】第二十五天 Vue3 与 Axios 后端数据交互

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue3 与 Axios 概述二、Axios 安装与基本使用2.1 安装 Ax…

NECCS|全国大学生英语竞赛C类|词汇和语法|语法题|时态|22:30~11:44

15题 10min 10:20&#xff5e;10:25 test2 10:25&#xff5e;10:47 test1订正 10:44&#xff5e;11:47 理论学习 涉及的语法点主要包括&#xff1a; 动词的时态和语态 非谓语动词 虚拟语气 主谓一致 倒装句 强调句 比较级 名词性从句 定语…

【SQL篇】面试篇之子查询

1303 求团队人数 # 写法1 # Write your MySQL query statement below select employee_id, count(*) over(partition by team_id) as team_size from Employee# 写法2 # Write your MySQL query statement below select employee_id, team_size from Employee e join (select t…

优雅编程,从空格、空行、缩进、注释开始

很多初学者的代码其实都不够“漂亮”&#xff0c;那是因为没有养成好的编码习惯。本篇博客以C语言为例&#xff0c;总结一些好习惯。其实&#xff0c;很多习惯都是肌肉记忆&#xff0c;举个例子&#xff1a;请你写一个程序&#xff0c;输入2个整数并输出它们的和。有些朋友可能…

springboot+vue前后端分离项目打包成jar包及运行

将 Spring Boot 和 Vue.js 项目打包成 jar 包需要按照以下步骤操作&#xff1a; 在项目的根目录中&#xff0c;使用命令行进入 Vue.js 项目的根目录&#xff0c;然后运行以下命令&#xff1a; npm run build这个命令将会构建 Vue.js 项目&#xff0c;并在项目的 dist 目录中生…