您现在的位置是:网站首页> 硬件

硬件学习及经验总结笔记

  • 硬件
  • 2024-11-27
  • 1128人已阅读
摘要

硬件学习及经验总结笔记

对于编译出现莫名其妙问题处理

对于编译出现莫名其妙问题可以重新下载板子驱动和开发库

***在工业控制板中每个单片机引脚都需要与控制的原件做光耦隔离***


Ardunio 板子开发包位置

Arduino的输出接口可以直接接固态继电器吗?

绘制Ardunio电路图Fritzing

Arduino 烧写bootloader

单片机上电执行过程

ardunio基础使用

程序加载过程说明

HEX烧录到单片机的原理

单片机的存储空间

MCU寄存器地址内存地址

单片机执行程序过程

单片机执行编制程序的全过程解析

常用经验及模块接口相关编程收集

AVR单片机

ROM RAM FLASH 介绍

STM32启动解析

伺服电机在Ardunio中有封装好的叫舵机,自控制代码

使用 Arduino IDE 编程你的 STM32,开启你的STM32之旅

STM32如何使用arduino_ide进行开发

初试STM32基于Arduino的使用

如何防止Arduino程序被抄板?

Arduino使用多个串口的方法

arduino如何采集电流(arduino输出可调电压)

逻辑电平转换器

pulseIn函数说明

Ardunio PWM

使用 Arduino IDE 编程你的 STM32,开启你的STM32之旅

手动安装Arduino板子库

你们的arduino 都是怎么独立供电的

中断使用注意

Ardunio软重新启动

Arduino的String类用法汇总

Arduino 极客教程

采用Enerlib程序库设定睡眠模式

Ardunio 命令行编译上传

Arduino休眠模式和看门狗以及中断详解

嵌入式工控机GPIO

常用电气符号

Arduino学习——Arduino main 函数

舵机和伺服电机有什么区别

电平转换模块 光耦继电器模块 MOS取代继电器





Ardunio 板子开发包位置

如:C:\Users\Administrator\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.5\libraries\WiFi



Arduino的输出接口可以直接接固态继电器吗?


Arduino 的输出接口在某些情况下可以直接连接固态继电器,但需要考虑以下几点:

一、电压匹配方面

Arduino 数字输出引脚输出的是 5V(对于标准的 Arduino 板,如 Uno)或 3.3V(如 Arduino Nano 33 BLE 等)的逻辑电平信号。大部分固态继电器的控制端输入电压范围比较宽泛,能够兼容 3 - 32V 的控制信号。所以从电压角度看,Arduino 输出引脚的电压通常可以满足固态继电器控制端的最低输入电压要求。

例如,一个典型的固态继电器控制端输入电压范围是 3 - 12V。当 Arduino 输出 5V 信号时,是可以在这个电压范围内驱动固态继电器的控制端。

二、电流驱动能力方面

Arduino 数字输出引脚的电流驱动能力有限。一般来说,Arduino 每个数字输出引脚最大能够提供 20 - 40mA(具体数值因型号略有差异)的电流。

固态继电器的控制端需要一定的电流来触发。虽然不同型号的固态继电器触发电流不同,但通常在几毫安到几十毫安之间。如果固态继电器的触发电流小于 Arduino 输出引脚能够提供的最大电流,那么从理论上讲,Arduino 可以直接驱动固态继电器。

例如,一个固态继电器的控制端触发电流为 5mA,而 Arduino 数字输出引脚能够提供最大 20mA 的电流,这样 Arduino 就有足够的能力为固态继电器的控制端提供触发电流。

不过,为了确保系统的稳定性和可靠性,尤其是在长期运行或者复杂的电气环境下,最好在 Arduino 输出引脚和固态继电器控制端之间连接一个限流电阻。这样可以防止意外的电流尖峰损坏 Arduino 或者固态继电器。电阻的阻值可以根据欧姆定律(R = V/I)来计算,其中 V 是 Arduino 输出引脚电压减去固态继电器控制端的工作电压(一般是在其工作电压范围下限),I 是固态继电器的触发电流。

三、电气隔离方面

虽然固态继电器本身具有一定的电气隔离功能(将控制电路和负载电路进行隔离),但是在实际应用中,如果连接的负载可能会产生干扰信号(如感性负载产生的反电动势),有可能会通过固态继电器的控制端影响到 Arduino。为了避免这种情况,可以考虑在 Arduino 和固态继电器之间增加光电耦合器等隔离器件,进一步增强系统的抗干扰能力。

Arduino 的输出接口在满足固态继电器的电压、电流要求的情况下可以直接连接固态继电器,但为了系统的稳定和安全,可能需要采取一些额外的措施,如连接限流电阻和隔离器件。


光电耦合器:

光电耦合器能够将输入侧的电信号转换为光信号,再将光信号转换为输出侧的电信号。这种转换过程可以实现信号的放大、整形等功能

1.png




单片机上电执行过程

在单片机上电后,会执行复位向量,即跳转到复位向量地址处执行,程序指针PC会被初始化为上电复位时的地址,从哪个地址处读取将要执行的指令。接着,单片机会执行初始化程序,包括初始化堆栈指针、初始化数据段、初始化代码段等。然后,单片机会执行主程序。在内核初始化的过程中主要做了以下几件事情:

1.内核复位和NVIC寄存器部分清零;2.内核设置堆栈:内核从向量表0地址读出堆栈地址,并设置主堆栈指针(SP_main);3.设置系统时钟;4.初始化中断向量表;5.调用main函数

单片机程序执行的过程分三个步骤:取执行->分析指令->执行指令。取指令的任务是:根据PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行


BootLoader

引导程序概念:

在系统上电或复位后运行的一段小程序。这段程序将系统的软硬件环境带到一个合适的状态,为最终调用应用程序准备好正确的环境。

主要功能:

将系统的软硬件环境带到一个合适状态,初始化硬件设备,完成处理器和周边电路正常运行所需要的初始化工作

建立正确的 内存空间的映射

从 ROM、Flash 等非易失存储器或网络上加载操作系统映像文件(或者用户应用程序映像/特定软件组件),拷贝到RAM,并且运行

初始化栈

检测并初始化内存,初始化全局变量

引导操作系统或执行用户应用程序


完成处理器和周边电路正常运行所需要的初始化工作:

设置 FCLK-内核时钟,是提供给CPU的时钟

设置 HCLK-总线时钟,是提供给用于存储器控制器,中断控制器的时钟

设置 PCLK-I/O接口时钟,是提供给用于外设如PWM 定时器,SPI的 APB (advanced peripherals bus)总线的时钟。

上电之后,如果什么都不设置,FCLK和晶振的频率相等。当设置PLL后,CPU并不是马上就使用设置好的高频时钟,而是有一段锁定时间,在这段时间里,CPU停止运行,等12MHz变成高频时钟稳定以后,整个系统再重新运行。


两种操作模式:单片机启动加载模式和下载模式。


启动加载模式:把控制权交给用户应用程序。

下载模式:BootLoader 通过串口连接或网络连接等手段从主机下载文件。

进入bootloader的方式

复位时 特定通信口的关键字检测

复位时 特定硬件IO检测

运行时 特定通信口的关键字检测



STM32启动解析

绝大多数人没有关注或并不关注类似STM32的MCU是怎么从上电运行到main()函数的

也许你会说可不就是直接给电就行吗?我啥也没配置,就轻松进入main()函数了。 其实,在上电前有两个引脚对MCU的启动有些关键的影响:BOOT0和BOOT1,这两个引脚的电平状态直接影响了芯片在复位上电后从芯片的哪个位置开始执行代码。

如果读者朋友已经有过汇编相关基础,能够够好理解本文内容。汇编语言是比C语言更接近机器底层的编程语言,能让我们更好的理解和操纵硬件底层。


STM32三种启动模式


下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存,这就是所谓的启动过程。


STM32上电或者复位后,代码区始终从0x00000000开始,其实就是将存储空间的地址映射到0x00000000中。三种启动模式如下:


·从主闪存存储器启动,将主Flash地址0x08000000映射到0x00000000,这样代码启动之后就相当于从0x08000000开始。主闪存存储器是STM32内置的Flash,作为芯片内置的Flash,是正常的工作模式。一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。


·从系统存储器启动。首先控制BOOT0、BOOT1管脚,复位后,STM32与上述两种方式类似,从系统存储器地址0x1FFF F000开始执行代码。系统存储器是芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。启动的程序功能由厂家设置。系统存储器存储的其实就是STM32自带的bootloader代码。


·从内置SRAM启动,将SRAM地址0x20000000映射到0x00000000,这样代码启动之后就相当于从0x20000000开始。内置SRAM,也就是STM32的内存,既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。假如我只修改了代码中一个小小的地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码,用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。


用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。STM32三种启动模式对应的存储介质均是芯片内置的,如下图:

1.jpg


串口下载程序原理


从系统存储器启动,这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。系统存储器是芯片内部一块特定的区域,STM32在出厂时,由ST在这个区域内部预置了一段BootLoader,也就是我们常说的ISP程序,这是一块ROM,出厂后无法修改。


一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。


这个下载方式需要以下步骤:


·将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader;


·在BootLoader的帮助下,通过串口下载程序到Flash中;


·程序下载完成后,又有需要将BOOT0设置为GND,手动复位,这样,STM32才可以从Flash中启动。


从汇编代码分析STM32启动过程


STM32的启动文件与编译器有关,不同编译器,它的启动文件不同。虽然启动文件(汇编)代码各有不同,但它们原理类似,都属于汇编程序。拿基于MDK-ARM的启动文件来举例,说一下要点内容。在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。

1.jpg


这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。可以使用STM32CubeMX对上面的数值大小进行配置:

1.jpg


在IAR中,是通过工程配置堆栈大小:

1.jpg


看下面的汇编代码,程序上电之后,是跳到Reset_Handler这个位置。


1.jpg

知道代码是从Reset_Handler开始执行,再来看如下Reset_Handler汇编代码。在启动的时候,执行了SystemInit这个函数。

1.jpg


执行完SystemInit函数,初始化了系统时钟,之后跳转到__main函数执行。


无论是哪种启动方式,上电之后,都会有一段BootLoader引导程序,如果是从内置flash启动,则直接从0x08000000地址开始读取;如果是从系统存储器启动,则从ISP引导程序开始,该地址位置根据不同芯片地址也不同,可以查看芯片手册找到起始地址。然后引导跳转到0x08000000,IAP程序+应用程序,若无IAP程序,则0x08000000存放的就是应用程序。 IAP程序即是我们常常关注的用户BootLoader程序,可以根据实际需求修改。




程序存储器一个“只读存储器”的别名,简写为ROM

1.为了定位ROM中的数据,每个8位存储单元都有一个固定的“地址”,通常用16进制数表示。例如,对于一个所谓4K的ROM,地址从0000H到0FFFH(即从0000,0001…4095),单片机运行时从哪个地址取数据,完全由程序本身决定,并不要我们干预。记住,给单片机一通电,它经过一个短暂的复位过程,立即转向ROM的最低地址0000H,在这里面放置的往往是一条“跳转”指令,它从这里一步跳到另一个地址:程序的真正起始地址,例如51机的0080H。ROM是程序存储器,除了指令外,还包括运行程序必须的某些固定数据,例如:数据表。假如,我们要求在单片机的接口上输出00H到FFH(255)按正弦半波变化的数值,每秒10000次。如果硬要它按照公式一个个计算,对于它来说未免力不从心。可是我们可以把预先计算好的数值存入ROM中,到时候直接取出不是好多了?又如一个重要的应用:大家一定见过不少单片机的东西上面都有数码显示,那些个数字其实就是用单片机的口线控制数码管的字段电极电位。这些字形也是存放在ROM中的字模表,各个字模和0-9的数字(机器内当然是0000-0101二进制数)对应起来。常见的共阳极7段数码管,必须在阳极加正电,7个阴极都是地电位,才能显示数字”8″,数字8对应的显示字码值是二进制数“10000000“(那个1对应的是小数点,高电位不让它显示)。

2.数据存储器RAM这是个可以随时存取数据的一块存储器,也就是可以读(取)也可以写(存)的存储器,简称RAM。现在的单片机里面使用的RAM,属于静态RAM或SRAM,这个和电脑用的内存条有所不同。只要你把数据写入SRAM后,不断电或者不清除掉,这个数据就一直保存在那里。电脑用的是动态RAM,要不断给它加刷新脉冲才能保存数据。因为单片机处理的信息量比电脑小很多,所以它带的RAM也比较少:从完全不带、带128、256、…1K、2K,到4K,比ROM少多了。因为实际上RAM只是作为数据临时存放的地方,除非进行图像处理需要存放大量的数据外。一般对于执行较简单任务的单片机,有这么多也够用,如果实在不够用也只能采取外加SRAM如6116、6264等等来扩展。除了对RAM单元存取8位二进制数,当然也得和ROM一样用“地址”来标示它的具体位置。假如某单片机有1K(1024)RAM,它的地址也是从0000到1024,或16进制数的0000H到03FFH。可见,和ROM的地址是一样的

3.会不会混淆不清?答案是不会的,因为读ROM是由单片机的程序指针或转移指令或查表指令进行,而这些指令是不会进入RAM区的;读写RAM是另外的数据传送指令,也不会进入ROM区。这点也是和电脑不同之处,后者程序和数据都在内存条里面,地址不同,如果窜位了就会造成不可预见后果。单片机的这种存储器结构也称为哈佛结构。


RAM在单片机里的用途,主要是存放临时数据。例如用单片机测温,每秒测1次,显示1分钟的平均值(1分钟更新一次):我们先通过传感器、放大电路、A/D转换,把温度这个模拟量转变为成比例的二进制数,然后每秒钟1次把数字量通过输入口顺序存入到单片机的RAM中,然后对他们进行两两求和再平均的计算,最后的数值显示出来,然后把这60个存储单元统统写0清除旧数据,下次又是如此循环进行


另外,在单片机里面还有若干寄存器,数量不多但是作用很大,除了暂存数据,还可以交换、加工、传递等等,以及随时记录单片机当前处于什么状态,输入输出口也是作为特殊功能的寄存器存在,具体各有不同,就不是随便说说可以搞清楚的,要看有关书籍,然后结合实际经验,或者关注安服优公众号,满满的干货等您来取哟。


单片机中的ROM,RAM和FLASH的作用

一、ROM,RAM和FLASH在单片中的作用

ROM——存储固化程序的(存放指令代码和一些固定数值,程序运行后不可改动)

c文件及h文件中所有代码、全局变量、局部变量、’const’限定符定义的常量数据、startup.asm文件中的代码(类似ARM中的bootloader或者X86中的BIOS,一些低端的单片机是没有这个的)通通都存储在ROM中。

RAM——程序运行中数据的随机存取(掉电后数据消失)

整个程序中,所用到的需要被改写的量,都存储在RAM中,“被改变的量”包括全局变量、局部变量、堆栈段。


FLASH——存储用户程序和需要永久保存的数据。

例如:现在家用的电子式电度表,它的内核是一款单片机,该单片机的程序就是存放在ROM里的。电度表在工作过程中,是要运算数据的,要采集电压和电流,并根据电压和电流计算出电度来。电压和电流时一个适时的数据,用户不关心,它只是用来计算电度用,计算完后该次采集的数据就用完了,然后再采集下一次,因此这些值就没必要永久存储,就把它放在RAM里边。然而计算完的电度,是需要永久保存的,单片机会定时或者在停电的瞬间将电度数存入到FLASH里。

二、ROM,RAM和FLASH在单片中的运作原理

1、程序经过编译、汇编、链接后,生成hex文件;

2、用专用的烧录软件,通过烧录器将hex文件烧录到ROM中

注:这个时候的ROM中,包含所有的程序内容:一行一行的程序代码、函数中用到的局部变量、头文件中所声明的全局变量,const声明的只读常量等,都被生成了二进制数据。

疑问:既然所有的数据在ROM中,那RAM中的数据从哪里来?什么时候CPU将数据加载到RAM中?会不会是在烧录的时候,已经将需要放在RAM中数据烧录到了RAM中?

答:

(1)ROM是只读存储器,CPU只能从里面读数据,而不能往里面写数据,掉电后数据依然保存在存储器中;RAM是随机存储器,CPU既可以从里面读出数据,又可以往里面写入数据,掉电后数据不保存,这是条永恒的真理,始终记挂在心。

(2)RAM中的数据不是在烧录的时候写入的,因为烧录完毕后,拔掉电源,当再给MCU上电后,CPU能正常执行动作,RAM中照样有数据,这就说明:RAM中的数据不是在烧录的时候写入的,同时也说明,在CPU运行时,RAM中已经写入了数据。

三、ROM中包含所有的程序内容,在MCU上电时,CPU开始从第1行代码处执行指令。这里所做的工作是为整个程序的顺利运行做好准备,或者说是对RAM的初始化(注:ROM是只读不写的),工作任务有几项:

(1)为全局变量分配地址空间---如果全局变量已赋初值,则将初始值从ROM中拷贝到RAM中,如果没有赋初值,则这个全局变量所对应的地址下的初值为0或者是不确定的。当然,如果已经指定了变量的地址空间,则直接定位到对应的地址就行,那么这里分配地址及定位地址的任务由“连接器”完成。

(2)设置堆栈段的长度及地址---用C语言开发的单片机程序里面,普遍都没有涉及到堆栈段长度的设置,但这不意味着不用设置。堆栈段主要是用来在中断处理时起“保存现场”及“现场还原”的作用,其重要性不言而喻。而这么重要的内容,也包含在了编译器预设的内容里面,确实省事,可并不一定省心。

(3)分配数据段data,常量段const,代码段code的起始地址——代码段与常量段的地址可以不管,它们都是固定在ROM里面的,无论它们怎么排列,都不会对程序产生影响。但是数据段的地址就必须得关心。数据段的数据时要从ROM拷贝到RAM中去的,而在RAM中,既有数据段data,也有堆栈段stack,还有通用的工作寄存器组。通常,工作寄存器组的地址是固定的,这就要求在绝对定址数据段时,不能使数据段覆盖所有的工作寄存器组的地址。必须引起严重关注。

注:这里所说的“第一行代码处”,并不一定是你自己写的程序代码,绝大部分都是编译器代劳的,或者是编译器自带的demo程序文件。因为,你自己写的程序(C语言程序)里面,并不包含这些内容。高级一点的单片机,这些内容,都是在startup的文件里面。

四、普通的flashMCU是在上电时或复位时,PC指针里面的存放的是“0000”,表示CPU从ROM的0000地址开始执行指令,在该地址处放一条跳转指令,使程序跳转到_main函数中,然后根据不同的指令,一条一条的执行,当中断发生时(中断数量也很有限,2~5个中断),按照系统分配的中断向量表地址,在中断向量里面,放置一条跳转到中断服务程序的指令,如此,整个程序就跑起来了。决定CPU这样做,是这种ROM结构所造成的。过程中中C语言编译器作了很多的工作,可仔细阅读编译器自带的help文件进行学习。


注:特别的,如下

1--I/O口寄存器:也是可以被改变的量,它被安排在一个特别的RAM地址,为系统所访问,而不能将其他变量定义在这些位置。

2--中断向量表:中断向量表是被固定在MCU内部的ROM地址中,不同的地址对应不同的中断。每次中断产生时,直接调用对应的中断服务子程序,将程序的入口地址放在中断向量表中。


 ROM的大小疑问:

对于flash类型的MCU,ROM空间的大小通常都是整字节的,即为ak*8bits。这很好理解,一眼就知道,ROM的空间为aK。但是,对于某些OTP类型的单片机,比如holtek或者sonix公司的单片机,经常看到数据手册上写的是“OTP progarming ROM  2k*15bit...”,可能会产生疑惑,这个“15bit”认为是1个字节有余,2个字节又不足,那这个ROM空间究竟是2k,多于2k,还是4k但是少了一点点呢?

答:这里要明确两个概念:一个是指令的位宽,另一个是指令的长度。指令的位宽是指一条指令所占的数据位的宽度;有些是8位位宽,有些是15位位宽。指令长度是指每条指令所占的存储空间,有1个字节,有2个字节的,也有3个字节甚至4个字节的指令。实事上也确实如此,当在反汇编或者汇编时,可以看到,复合指令的确是有简单的指令组合起来的,因此,OTP的ROM空间应该是2K,指令位宽为15位。一般的,当指令位宽不是8的倍数时,则说明该MCU的大部分指令长度是一个字节(注:该字节宽度为15位,不是8位),极少数为2个或多个字节,虽然其总的空间少,但是其能容下的空间数据并不少。


五、flash

关于flash,在单片机中需要外接,且需要cup具有SPI接口

例如:25PE80V6、25080BVSIG等


伺服电机在Ardunio中有封装好的叫舵机,自控制代码

//控制舵机

void initServo(int ServoPin)

{

  turnAngle = 90;

  pinMode(ServoPin, OUTPUT);

  digitalWrite(ServoPin, LOW);//先保证拉低

  //ServoControl(12, 0);

}

long xnmap(long x, long in_min, long in_max, long out_min, long out_max)

{

  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

}


void ServoControl(int ServoPin, int servoAngle)

{

  double thisAngle = xnmap(servoAngle, 0, 180, 500, 2500);//等比例角度值范围转换高电平持续时间范围

  unsigned char i = 50;//50Hz 每秒的周期次数(周期/秒) 即1S 50 个周期 每个周期20ms

  while (i--)

  {

    digitalWrite(ServoPin, HIGH);

    delayMicroseconds(thisAngle); //高电平时间

    digitalWrite(ServoPin, LOW);

    delayMicroseconds(20000 - thisAngle);//每个周期20ms减去高电平持续时间

  }

}


AVR单片机

AVR单片机是1997年由ATMEL公司研发出的增强型内置Flash的RISC(Reduced Instruction Set CPU) 精简指令集高速8位单片机。可以广泛应用于计算机外部设备、工业实时控制、仪器仪表、通讯设备、家用电器等各个领域

如何防止Arduino程序被抄板?

有两个简单粗暴的方法,

其一,录好程序接好线,烧录口和主芯片直接灌注树脂或其他胶。

还有一种方法,设个开关,只要烧录口有电压信号,就闭合开关,直接短路烧毁芯片。

这两个笨方法我们团队一直在用,给您做参考~

外置SHA204加密芯片,配合上里面的代码

为了防止自己辛辛苦苦开发了产品被别人抄板仿制,我们使用了ATSHA204A的认证功能。在应用启动的时候,首先我们要验证PCBA上焊接的ATSHA204A芯片中存放的密钥是否匹配,如果不匹配将程序挂起;如果密钥匹配继续往下执行。如果没有ATSHA204A芯片,程序也会挂起。为了增强破解难度,在程序中重要功能调用前也都加入密钥验证操作。


        ATSHA204A芯片里的数据本身是不可复制的,而我们的目标代码必须配合对应的芯片才能运行。即使“坏人”从存储器中读出目标代码也不能运行,从而达到防抄板仿制目的。


        通过专用编程器,将16组密钥写入ATSHA204A芯片,并配置好相应权限。PCBA贴片前烧录好芯片,当然你也可以选择在线烧录。为了防泄密,最好由专人操作。密钥一旦设置就不会轻易变动,所以能看到密钥明文的人越少越安全。我的做法是采用某个目标文件中一段数据,16组密钥在源文件中不连续放置。这样即使你用二进制工具打开目标文件,密钥看起来也会像是某段程序。验证时只需指定组编号而不用密钥明文。


也许有人有疑惑,解释一下:


1、能否在I2C总线上截获密钥?

   ——在I2C总线上并没有传送密钥,而是传送根据秘钥和一组随机数计算出来的digest,因此在总线上截获密钥不可实现。

2、在目标代码中包含密钥,别人从存储器中读取目标文件后是否有可能得到密钥?

   ——目标文件中的确实存有密钥,但是在一个几十MB的二进制文件中寻找一组32字节的密钥,岂不是大海捞针?

3、是否有破解的可能?

   ——对于一些小单片机(51之类的),的确好破,反汇编后,跳过验证步骤即可。但是对于功能强大的MPU,就算你能反汇编,也得找出验证步骤在哪里。因此,只要密钥不泄露,要破解相当困难。


Arduino使用多个串口的方法

其实Arduino官方提供了一个软串口的库SoftwareSerial,不需要额外的去库管理面板中导入,只需一句include语句就可以使用它

#include <SoftwareSerial.h>

这个库可以将Arduino的引脚,通过程序模拟成串口来使用;

在声明语句中使用

SoftwareSerial mySerial(2,3);

便创建了一个自定义的软串口mySerial,并把数字引脚2定义成RX,数字引脚3定义成TX

#include<Servo.h>

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2,3); //定义D2、D3分别为TX、RX

Servo myservo;

int pos = 0;


void setup()  

{  

 mySerial.begin(9600);  //以9600波特率打开软串口

 myservo.attach(9); //舵机控制引脚9

 myservo.write(0);

 delay(10000);

}  


void loop()  

{   

   while(mySerial.available())  

   {  char c;

      c=mySerial.read();

      mySerial.println (c);

      switch(c){

        case '2':open_the_door();

        break;

        }

   }

   

}


void open_the_door(){

    for (pos = 0; pos <= 180; pos += 1) { 

    myservo.write(pos);            

    delay(5);                       

  }

}


arduino如何采集电流(arduino输出可调电压)

电路分为多个功能块进行介绍。 这样可以更清楚地知道电路是如何工作的。


测量单元


测量单元包括分压器,有助于测量电压。 非反向的运算放大器可以测量通过电路的电流。 上述电路的分压部分如下。


这里的输入电压用Vcc表示,如上所述,设计了从0到24V的电压范围的电路。 但是,像Arduino这样的微控制器不能测量这么高的电压值,只能测量0-5v的电压。 因此,必须将0-24v的电压(转换)为0-5v。 因此,如下所示,使用分压电路实现。 10k和2.2k的电阻形成分压电路,可以通过下式计算分压器的输出电压。


vout=(vinR2 )/(R1 R2 )


电路图中标记为Voltage的电压来自两个电阻的中间,该转换后的电压可以输入到Arduino的模拟针中。 其次是电流测量单元。 我们知道微控制器只能读取模拟电压,所以需要将电流值转换为电压。 此时,可以通过在电路中追加(并联)电阻来实现。 根据欧姆定律,电压值与其流过的电流成比例下降。 这样得到的值非常小,所以使用运算放大器进行放大。 电路如下。


分流电阻(SR1 )的值为0.22欧姆。 如上所述,我们设计了0-1A的测量电路。 根据欧姆定律,可以计算该电阻的压降。 最大的1A电流通过负载时,其电压为0.2V左右。 该电压对微控制器来说非常小,所以使用运算放大器将电压从0.2V放大到更高。 该放大器的增益为21,因此0.2*21=4.2v。 计算运算放大器增益的公式如下。


gin=vout/vin=1(RF/rin ) ) ) ) ) ) ) )。


在示例中,Rf的值为20k,Rin的值为1k。 由此,得到21的增益值。 然后,将放大器的放大电压输入到由电阻器1k和电容器0.1uf组成的RC滤波器电路中,以去除耦合噪声。 最后,将得到的电压输入到Arduino模拟针中。


测量单元的最后一部分是电压调整电路。 实际输入的电压可能是可变的,Arduino和运算放大器需要稳定的5V才能保证正常工作,因此使用了7805稳压模块,并添加了噪声电容器进行了电压调整。 电路如下。


计算和显示单元


测量单元将电压和电流参数转换为0-5v,可用于Arduino模拟输入。 现在,您需要将这些电压信号连接到Arduino,并将1602液晶显示器连接到Arduino,以查看最终结果。


如上图所示,Voltage引脚连接到Arduino模拟引脚A3,Current引脚由Arduino模拟引脚a 4、1602液晶显示器的电源由7805输出的5 V提供,同时1602其他信号引脚由Arduino数字引脚提供


Arduino编程部分


硬件的部分讨论结束后,现在轮到软件部分了。 软件代码的基本思想是读取A3和A4的模拟电压,计算电压、电流、功率值,最后显示在液晶屏上。 把代码分成短的部分来说明吧。 与所有Arduino程序一样,它最初是用于定义的管脚。 在本例中,A3和A4引脚分别用于测量


量电压和电流,数字针3,4,8,9,10和11用于与Arduino进行交互。

int Read_Voltage = A3;


int Read_Current = A4;


const int rs = 3, en = 4, d4 = 8, d5 = 9, d6 = 10, d7 = 11; //1602 LCD 连接针


LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


included一个名为“liquid crystal”的头文件。然后setup 函数中,初始化LCD显示屏,并将串口显示文本设置为“Arduino Wattmeter”,然后等待两秒钟。代码如下所示:


void setup() {


lcd.begin(16, 2); //Initialise 16*2 LCD


lcd.print(" Arduino Wattmeter");


lcd.setCursor(0, 1);


lcd.print("-Circuitdigest");


delay(2000);


lcd.clear();


}


在主循环函数中,我们使用analogread函数来读取A3和A4的电压值。我们知道Arduino ADC的输出值是0-1203,因为它有一个10位的ADC,这个值必须被转换成0-5v,可以通过乘以(5/1023)来完成。在硬件介绍部分,我们已经完成从0-24v到0-5v的电压转换,以及0-1a到0-5v的转换。所以现在我们要用一个乘数把这些值恢复到实际值。可以通过将其与乘数值相乘来完成。乘数的值可以用硬件部分提供的公式来计算,或者如果你已知电压和电流值,你可以实际计算它。本例遵循了后一种选择,因为它在现实中往往更准确。所以乘数的值是6.46和0.239。因此,代码如下所示:


float Voltage_Value = analogRead(Read_Voltage);


float Current_Value = analogRead(Read_Current);


Voltage_Value = Voltage_Value * (5.0/1023.0) * 6.46;


Current_Value = Current_Value * (5.0/1023.0) * 0.239;


如何提高测量精度?


上述计算实际电压和电流值的方法可以很好地工作。但是也有一个缺点,那就是测量的ADC电压和实际电压之间的关系不是线性的,因此得到的结果不会非常精确。为了提高精确度,我们可以用已知的一组值来建立测量的ADC值的集合,然后利用这些数据,使用线性回归方法推导出乘数方程。一旦我们计算出了实际电压和实际电流值,我们就可以用公式计算出功率(P=V*I)。然后使用下面的代码在LCD上显示这三个值。


lcd.setCursor(0, 0);


lcd.print("V="); lcd.print(Voltage_Value);


lcd.print(" ");


lcd.print("I=");lcd.print(Current_Value);


float Power_Value = Voltage_Value * Current_Value;


lcd.setCursor(0, 1);


lcd.print("Power="); lcd.print(Power_Value);


完整测试代码


/*


* Wattmeter for Solar PV using Arduino


* Dated: 2-10-2018


* Website: www.basemu.com


* Translation to:circuitdigest.com


* Power LCD and circuitry from the +5V pin of Arduino whcih is powered via 7805


* LCD RS -> pin 2


* LCD EN -> pin 3


* LCD D4 -> pin 8


* LCD D5 -> pin 9


* LCD D6 -> pin 10


* LCD D7 -> pin 11


* Potetnital divider to measure voltage -> A3


* Op-Amp output to measure current -> A4


*/


#include


int Read_Voltage = A3;


int Read_Current = A4;


const int rs = 3, en = 4, d4 = 8, d5 = 9, d6 = 10, d7 = 11;


LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {


lcd.begin(16, 2);


lcd.print(" Arduino Wattmeter");


lcd.setCursor(0, 1);


lcd.print(" With Arduino ");


delay(2000);


lcd.clear();


}


void loop() {


float Voltage_Value = analogRead(Read_Voltage);


float Current_Value = analogRead(Read_Current);


Voltage_Value = Voltage_Value * (5.0/1023.0) * 6.46;


Current_Value = Current_Value * (5.0/1023.0) * 0.239;


lcd.setCursor(0, 0);


lcd.print("V="); lcd.print(Voltage_Value);


lcd.print(" ");


lcd.print("I=");lcd.print(Current_Value);


float Power_Value = Voltage_Value * Current_Value;


lcd.setCursor(0, 1);


lcd.print("Power="); lcd.print(Power_Value);


delay(200);


}


逻辑电平转换器

与Arduino一起,我们肯定会使用各种传感器,例如IR传感器,PIR传感器和超声波传感器。但是问题是当今大多数电路板不能承受5 V的电压,但是有恰巧几乎所有电路板都可在3.3V电压下工作。


这是否意味着我们不能再使用旧的传感器了?


不完全是。如今,几乎所有的微控制器都在3.3V逻辑下工作。大多数在3.3V电压下工作的设备不提供5V电压,它们会在几秒钟内被烧毁。那么我们能做些什么呢?有一种方法可以将5V转换为3.3V的逻辑电平转换器。比如74LVC245。


74LVC245逻辑电平转换器IC


该芯片解决了将数据从5 V逻辑电平设备连接和发送到3.3 V逻辑微控制器(如Raspberry Pi和Arduino)的问题。该芯片位于Arduino和传感器之间,并将传感器的5V信号转换为3.3V,可以直接馈送到Arduino。


74LVC245可以用于数字信号,并且可以与SPI,串行,并行总线和其他逻辑接口配合使用。


制作PCB


表面安装技术是通过将组件安装在电路板表面上来组装PCB的技术。与传统的通过孔放置组件并将其焊接在另一侧的传统方法不同,在SMT中,将组件放置在板上,并且将引线焊接在同一侧。


设计电路74LVC245逻辑电平转换器IC


你可以轻松地访问EasyEDA网站并开始一个新项目。打开原理图设计后,开始添加组件,5V至3.3V逻辑电平转换器电路图

1.png


在EasyEDA中绘制原理图时,请确保从该列表中添加组件。您甚至可以搜索组件并检查其可用性。


从库中搜索组件并将其放置在画布中。使用“电线”工具将组件连接在一起。


使用该IC非常简单。您可以在几分钟内完成电路设置。


只需将VCC连接到要转换为的逻辑电平即可。如果要将5V转换为3.3V,则将3.3V连接到VCC。


地面连接到地面


OE(输出使能)接地以启用芯片


DIR至VCC(3.3V)



pulseIn函数说明

介绍一下pulseIn()函数

pulseIn()函数用来读取一个引脚的脉冲(HIGH或LOW)。例如,如果value是HIGH,pulseIn()会等待引脚变为HIGH,开始计时,再等待引脚变为LOW并停止计时。返回脉冲的长度,单位毫秒。如果在指定的时间内无脉冲函数返回。


计时范围从10微秒至3分钟。(1秒=1000毫秒=1000000微秒)


语法:

pulseIn(pin, value) 

pulseIn(pin, value, timeout)


参数:

pin:你要进行脉冲计时的引脚号(int)。 

value:要读取的脉冲类型,HIGH或LOW(int)。 

timeout (可选):指定脉冲计数的等待时间,单位为微秒,默认值是1秒(unsigned long)


Arduino里的PWM

首先,Arduino Uno的5,6,9,10,3,11接口可以通过简单语句analogWrite(pin, dutyCycle)来实现一个指定占空比的PWM。其中pin的值选择(5,6,9,10,3,11),dutyCycle的值在0~255之间,0为占空比0%,255为占空比100%。但是这种方式PWM信号的频率是固定的默认值,大约1000Hz左右(16MHz/64/256)。


其次,手动切换高电平和低电平,再在中间加入delay函数,可以实现自定义频率的PWM:


void setup()

{

  pinMode(13, OUTPUT);

}


void loop()

{

  digitalWrite(13, HIGH);

  delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz

  digitalWrite(13, LOW);

  delayMicroseconds(1000 - 100); //修改这里的1000可以调整频率

}


使用 Arduino IDE 编程你的 STM32,开启你的STM32之旅

许多电子爱好者和工程师开始接触电子产品时,Arduino是他们的第一块开发板。然而,随着接触越多和深入挖掘,很快就意识到 Arduino 还没有为工业做好准备,而且它的 8 位 CPU 的速度非常慢,不能为您的项目提供足够的动力。


不过,现在市场上有新的STM32F103C8T6 STM32开发板,它拥有 32 位的 CPU 和ARM Cortex M3 架构可以轻松超越 Arduino 。并且我们可以使用Arduino IDE对STM32板进行编程。


在本文中,我们开始使用 STM32F103C8T6,了解有关此板的一些基础知识并使用 Arduino IDE对其编程, 实现板载 LED 灯闪烁。


STM32(Blue Pill)开发板介绍

STM32F103C8T6 开发板是 ARM Cortex M3 微控制器的开发板。它看起来与 Arduino Nano 非常相似,如下图所示。

1.png


它上面的单片机芯片是 STMicroelectronics 的STM32F103C8T6,该MCU 可以在深度睡眠模式下运行,非常适合使用电池供电的应用。


由于 MCU 的工作为3.3V,因此该板还包含一个 5V 至 3.3V 的降压 IC为 MCU 供电。即使 MCU 在 3.3V 下运行,它的大多数 GPIO 引脚都可以承受 5V。


开发板上有两个板载 LED,一个(红色)用于电源指示,另一个(绿色)连接到 GPIO 引脚 PC13。它还有两个插针引脚(跳线帽),可用于切换不同的模式。


STM32 引脚详情

STM32 Blue Pill 板的完整引脚如下所示。正如你所看到的,G 表示接地引脚,3.3V 输出稳压 3.3V,5V 引脚可用于为电路板供电或通过微型 USB 获得+5V供电。板载 LED 连接到微控制器的 PC13引脚。


1.png

与 Arduino 板不同的是,STM32 通过 boot 1 和 boot 0 切换不同模式。


一般情况下,Boot 1 的位置通常保持不变,把boot 0 跳线设置为 3.3V 用于串口下载,或者设置为接地用于上电或复位后进入正常工作。


如何编程 STM32F103C8T6

STM32 只是 STMicroelectronics 系列的另一个微控制器。因此,现有的 ARM 芯片编程方法也可以用于 STM32 板。


Keil ARM MDK 是一种著名且常用的 IDE,除此之外我们还可以使用 IAR workbench、Atollic TrueStudio、MicroC Pro ARM、Crossworks ARM、Ride 7、PlatformIO+STM32 等。


但是,使该板广受欢迎的原因之一在于它能够使用 Arduino IDE 进行编程。许多arduino爱好者通过这种方式,可以立即开始使用 STM32 构建项目,因为他们熟悉 Arduino IDE 及其易于使用的编程语言和现成的库。所以这篇文章中,我们使用Arduino IDE 开始 STM32。


FTDI连接图

使用 Arduino IDE 对 STM32 Blue Pill 板进行编程,我们需要使用串行板FTDI。该板连接到 STM32 的 Rx 和 Tx 引脚,如下所示。

1.png


FTDI板的Vcc管脚连接到板子供电的STM32 5V管脚。地连接到STM32的地。FTDI板的Rx和Tx引脚分别连接到STM32的A9和A10引脚。其中 A9 是 STM32 MCU 的 Tx 引脚,A10 是 Rx 引脚。

1.png


为 STM32准备 Arduino IDE

按照以下步骤安装并准备与 STM 32 开发板一起使用的 Arduino IDE。


第 1 步:安装Arduino IDE。


安装步骤(略)


第 2 步:安装 Arduino IDE 后,打开并下载 STM32 开发板所需的包。这可以通过选择“文件 -> 首选项”来完成。


1.jpeg

第 3 步:单击“首选项”将打开下面显示的对话框。在 “附加开发板管理器网址”文本框中粘贴以下链接,点击 “好”。


http://dan.drown.org/stm32duino/package_STM32duino_index.json


1.png

第 4 步:转到 工具 -> 开发板…->开发板管理器。这将打开“开发板管理器”对话框,搜索“STM32F1”并安装出现的包。


1.png

1.png


第5 步: - 安装完成。转到“工具”并向下滚动找到通用 STM32F103C 系列,选中如下图:

1.png


第 6 步: 现在,将 FTDI 板连接到计算机,并在设备管理器检查 FTDI 板连接到哪个 COM 口。然后,在“工具”->“端口”中选择相同的端口号:

1.png


第 7 步: 完成所有设置后,检查 Arduino IDE 的右下角,显示了已经配置的信息。我的 FTDI 板连接到 COM3,但你的可能不同,但是芯片信息确保为 64kFlah 类型,CPU 速度为 72MHz,上传方式为 Serial。

1.png


到这里 Arduino IDE 已准备好对 STM 32 Blue Pill 开发板进行编程了。


上传示例代码到STM32f103c8t6

让我们将板载LED闪烁示例程序从 Arduino IDE 上传到 STM32 Blue Pill 板。示例程序可以在 文件—>示例 中找到。

1.png

在打开的示例代码中,我们必须做一点小小的修改。默认情况下,该程序是为PB1编写,但在我们的开发板上,板载LED连接到PC13,因此将所有PB1更换为PC13。最后会给出修改后的完整示例程序。


loop函数内部的代码如下所示,我们可以注意到 PC13 引脚保持高电平(开启)1000 毫秒,然后再转低(关闭)1000 毫秒,高低一直循环。因此,LED 以 1000 毫秒的间隔闪烁。


digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level)


delay(1000); // wait for a second


digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW


delay(1000); // wait for a second


如前所述,在上传任何程序之前必须将 STM32 板设置为串口上传模式,为此将boot 0 跳线置于低电平。如下所示:

1.png


确保 boot 0 短接1的位置,然后按下复位按钮,绿色 LED 熄灭,这表明板子已准备好上传。点击 Arduino IDE 上的上传按钮,您的程序应该被编译和上传。

1.png

如果程序成功上传,您应该会看到绿色 LED 以 1 秒的间隔闪烁。您还可以修改程序,增加或减少延迟来改变闪烁速度。


上传程序后,boot 0 应该短接回0位置,这样下次板子上电时,上传的程序就开始自动执行了。


本文到此结束,希望能对你开始使用Arduino IDE 编程STM32有一点帮助。

手动安装Arduino板子库


手动安装ardunio板子库,可能是由于内容开始是网络地址(http://...)完整的英文词截取后不能换行造成 为避免代码造成手机端排版的混乱,可适当增加文字描述,将代码往后推移

esp8266开发板管理器地址

http://arduino.esp8266.com/stable/package_esp8266com_index.json

esp32开发版管理器地址

https://dl.espressif.com/dl/package_esp32_index.json

————————————————

我这里需要安装的开发板是 MisfitTech SAMD Boards,按照正常流程,添加附加开发板管理器网址:

1.png

但是在开发板管理器进行开发板安装的时候,出现了下载出错:

2.png


解决方法

第一步:将附加开发板管理器网址复制到浏览器进行访问,我们会访问到一个JSON文件:

3.png


这是一个对附加开发板进行描述的文件,右击进行保存,注意不要重命名。


第二步:打开上面的下载JSON文件:

复制 url 后面的链接到浏览器访问,浏览器会自动将压缩包下载,这是安装附加开发板所需要的库

4.png

到这一步我们会得到两个文件:

5.png

一个是附加开发板的库,一个是开发板的描述文件。

hfs.rar

第三步:打开 HFS软件,将我们下载好的开发板库的压缩文件导入:

6.png

然后我们复制上面的文件的链接地址。


第四步:打开上面下载好的JSON文件,将 url 后面的地址替换成我们上一步复制的那个链接地址,然后保存:

7.png

第五步:将这个JSON文件也导入到 HFS软件里,并且复制它对应的链接地址:

8.png

这个时候我们需要把 HFS软件挂到后台,切记一定不要关闭。


第六步:打开Arduino ,将上一步复制的JSON链接地址,填入到 附加开发版管理器网址 这个地方:

9.png

保存,然后打开开发板管理器就可以看到自己想要的开发板了


10.png

然后点击安装即可。

11.png

安装成功,开发板里也有对应的开发板选项了:

12.png13.png

安装后的板子一般位于:C:\Users\Administrator\AppData\Local\Arduino15\packages\

1.png


















上一篇:物联网硬件公司

下一篇:画面撕裂

Top