火辣西米秀

  • 2022-05-22
  • 发表了主题帖: 物联网小项目-智能农业灌溉系统

     

  • 2022-05-12
  • 发表了主题帖: MM32F5 系列漫谈 :吞吐率最大化的总线设计

    目 录   MM32F5270 的总线架构   案例:带显示的音频播放器   小结 & Next   上一篇文章介绍了 MM32F5 系列 所采用的 “星辰”STAR-MC1 处理器,如果读者还有印象的话,“星辰”处理器相较于 M3 和 M4 处理器的一个主要优势是引入了内存子系统,包括了L1 指令和数据缓存接口和紧耦合 TCM 接口。而仅有内存子系统是不够的,需要配合高效率的总线架构设计来实现其功能最大化。   本期,笔者就来聊聊 MM32F5270 的总线架构设计,看看 F5270 是如何通过高并行度的总线设计实现系统吞吐率的最大化。   MM32F5270 的总线架构✦ 下图展示了 MM32F5270 的总线架构,可以看到,系统中的处理器、存储和外设是通过一个零延迟 AHB 总线矩阵进行互联,这里的总线矩阵是一个多 Master 到多 Slave 的多层 AHB 总线结构。这里,把可发起读写访问的一方叫做 Master,响应访问的一方叫做 Slave。 注:AHB 属于 Arm® AMBA® 通信接口协议的一种,是嵌入式系统中的常用接口协议之一,对于不了解 Arm® AMBA® 接口协议的读者,可自行搜索相关资料,本文不再赘述。 总线 Master – 访问发起者✦   从上图可以看到,MM32F5270 中包含了如下 AHB 总线 Master: CPU – “星辰”STAR-MC1 DMA1 DMA2 USB 控制器(USB FS) 以太网控制器(ENET) 其中,“星辰”处理器占据 三个 AHB 口,分别是系统总线AHBS(system bus),代码总线 AHBC(code bus),以及 TCM 总线 AHBT(TCM bus)。其中 AHBC 和 AHBS 是处理器发起访问,从外部获取数据和指令的通路,而 AHBT 是处理器以外的其它 Master(如 DMA等)访问内部 TCM 的通路,也就是说,TCM 不仅能被 CPU 访问,外部资源也可以将 TCM 当作普通 SRAM 访问。 其它Master 包括 DMA、USB 和以太网。在 MM32F5270中,为提高系统并行度,配置了两路独立的 DMA 控制器,每个 DMA 控制器包含 8 个通道,每路 DMA 都可以无需 CPU 干预而进行 Slave 的读写访问。USB 和以太网也可以做为总线 Master 直接发起对系统存储的访问,例如将提前放置在 SRAM 中的数据搬移到 TX FIFO 中以实现无需 CPU 干预而进行的数据通信。 总线 Slave – 访问响应者✦ MM32F5270 中包含了如下 AHB 总线 Slave: 256KB 内置 Flash 存储器 112KB SRAM1 16KB SRAM2 QSPI – 可外扩四线 NOR Flash FSMC – 8/16/32 位并口,可外扩 SRAM,NOR Flash,8080/6800 屏 外设 APB1 组 外设 APB2 组   32KB ITCM和 32KB DTCM – 通过 AHBT 总线访问   为提高系统并行度,MM32F5270配备了两路独立的 RAM,包括 112KB 的 SRAM1 和 16KB 的 SRAM2,每个 RAM有独立的 RAM 控制器和 Slave端口。 此外,MM32F5270 还配备了 32KB 指令 TCM RAM(ITCM)和 32KB 的数据 TCM RAM(DTCM)。这里, TCM 和 CPU 是通过 TCM 接口直连的,相当于一条快速通道,CPU 访问 TCM 不需要经过外部总线矩阵,这也是 TCM 被称为紧耦合存储(Tightly-Coupled Memory,TCM)的原因。CPU 访问 TCM 是没有任何延迟的,因此也不需要经过缓存。同时,“星辰”处理器也预留了 AHBT 总线供 DMA 等 CPU 外部 Master 访问 TCM。这里的 AHBT 总线挂在总线矩阵的 Slave 端,也就是说,DMA 要访问 TCM 需要先经过总线矩阵。当 DMA 和 CPU 同时访问 TCM 时,“星辰”处理器以 CPU 访问为高优先级进行仲裁。需要说明的是,ITCM 支持程序执行和数据读取,其起始地址为 0x0000_0000,DTCM 支持数据读取,其起始地址为 0x2000_0000。 根据上述介绍可以得出,MM32F5270 里实际是配置了 4块完全独立的 RAM,包括 ITCM,DTCM,SRAM1 和 SRAM2,在某些应用场景下,这 4 块 RAM 能够同时被不同的 Master 访问而不会产生任何的总线冲突和等待。例如,CPU 可以读取并执行ITCM中存放的程序算法,以太网可以从 SRAM2 中读写数据,DMA1 可以从 DTCM中搬数据, DMA2 可以从 SRAM1中搬数据,这里的四条通路是完全独立和并行的。 MM32F5270还包含了两路独立的 APB 外设组,即 APB1 和 APB2,每个外设组有独立的 Slave 端口和AHB到 APB 的协议转换桥。 与此同时,用户还可以通过 FSMC 去外扩并口 NOR Flash 或者 SRAM,也可以通过 QSPI 去外扩四线式 NOR Flash。且这里的 FSMC 和 QSPI 都是直接挂在零延迟 AHB 总线矩阵上的 AHB Slave,因此其访问通路是完全独立的。当然,用户也可以通过 SPI、UART等串行总线接口来扩展更多存储空间,不过这些外设都是挂在 APB 总线上,和其它共同挂在 APB 总线的外设共享总线矩阵的 AHB Slave 端口,因此,可能会产生多余的等待周期。 需要说明的是,除了 TCM 和外设空间,从 Code bus 和 System bus 上读取的指令和数据基本上都可以被 4KB 指令缓存和 4KB 数据缓存加速。 下表对 MM32F5270 中支持的 Flash 和 RAM 资源做一个总结: 并发网络✦   前文提到的总线结构图中,Master 和 Slave 的连接关系通过矩阵网络上的空心圆表示,如内置 Flash 仅可以被 CPU 的 code bus 或者 DMA 访问,而不能被其它总线 Master 访问。 基于上述描述所能达到的效果就是,多个 Master 可以同时发起对多个Slave的访问,如果每条路径的发起者(Master)和响应者(Slave)都是不同的,那这些访问是完全并行的,是不需要仲裁和等待周期的。 下图是一个并发访问的例子,这里,6个总线 Master 对 6 个总线 Slave 的访问构成了 6 个独立通路。当然,这里仅仅是一个极限情况,对于一个实际应用所能达到的并发效果,需要根据应用需求具体分析。   案例:带显示的音频播放器✦ 为了更直观的讲解 F5270 多并发总线设计的强大,这里以一个实际应用的案例来进行展示。需要说明的是,这里的案例仅仅为了讲解功能,并不做为参考设计。 这里,考虑基于 MM32F5270 制作一个带显示的音频播放器,这是一种很常见的应用场景,实际产品中所包含的功能可能是多种多样的,这里为了简化,以如下规格要求为例:   可播放 SD 卡上的音频文件,支持 WAV 和 MP3 格式   2.4寸屏,320x240 分辨率,GUI 交互 注:实际的产品可能有更多的功能,如更高清的显示、USB扩展、WIFI 或蓝牙联网、视频播放、触控等,感兴趣的读者可以搜索下网络上的相关产品。 基于这个要求,可以搭建一个带显示的音频播放器,根据 MM32F5270 所包含的片内资源,对上述规格要求做出如下的功能分解和资源分配: 其对应的简易系统框图如下: 分析可知系统的主要功能可以分为三块: 第一块是 CPU 处理部分。   首先, CPU 所执行的主程序存放在内置 256KB Flash 中,而运行中所需要内存存放在 SRAM1 中,其数据通路如下图中的蓝色箭头所示;   同时,CPU 需要从外部 SD 卡读取音频文件,这里涉及到文件系统的交互,以及 MP3 软解码运算,并将解码后的音频数据存放在 32KB DTCM 中,其数据通路如下图中的黄色箭头所示;   最后,CPU 需要运行 GUI 应用程序,包括从外扩 Flash 中获取显示数据和字库,通过 CPU 的运算并将待显示的图像缓存到外扩 SRAM 中,其数据通路如下图中的绿色箭头所示。 第二块是音频播放数据流控制。 这里,通过 DMA1 来处理音频数据流,DMA1 通过 AHBT 总线从 DTCM 中读取解码后的音频数据,并写入 I2S 的 TX FIFO 中,通过 I2S 和外部的功放通信并驱动扬声器或耳机,其数据通路如下图中的红色箭头所示。 第三块是图像显示数据流控制。 这里,通过 DMA2 来处理图像显示数据流,DMA2 通过 FSMC 从外部 SRAM 中读取待显示图像,并通过 FSMC 写入外部 LCD 屏,实现图像帧的周期性刷新,其数据通路如下图的紫色箭头所示。 基于上述分析,将所有路径进行汇总,并删掉非独立路径后(即两条路径有共同发起者或共同接收者),可得到下图所示的汇总数据通路。可以看到,主程序的指令获取和执行(蓝色箭头)、主程序数据读写(蓝色箭头)、音频数据流(红色箭头)和GUI数据流(紫色箭头)这四条通路是完全独立的。假设系统运行在 120MHz,而所有访问都采用 32 位宽,则可以计算出此时整个系统的并行吞吐率可达 15Gbps! 当然,这里仅仅是一个精简的例子,对于实际应用,其所需功能可能会更加复杂。但重要的是,MM32F5270 的多并发总线架构为各类实际应用中的并行处理场景提供了硬件支持,使系统整体吞吐率有了大幅优化的空间。 需要补充说明的是,这个例子里面并没有用到 SRAM2 和 ITCM 等资源,因此其可以用作其他用途,如 SRAM2 可以用作 ENET、USB 、CAN 或者 ADC的数据缓存,而ITCM 中可以存放对实时性要求较高的算法或中断服务程序等。如果把这些功能都开发起来,则系统吞吐率是否还可以进一步提高呢?这个问题就留给感兴趣的读者来思考吧😊。   小结 & NEXT✦ 本文介绍了MM32F5270 中所采用的多并发总线架构,并通过带显示的音频播放器的实例说明了该架构在实际应用中所能达到的吞吐率提升效果。

  • 2022-05-10
  • 发表了主题帖: 灵动赞助的第十七届智能车竞赛的无刷驱动方案开源啦

    逐飞基于灵动MM32SPIN27PS的无刷驱动开源项目 由灵动微电子赞助的第十七届智能车竞赛的极速越野组允许使用无刷电机,且这个赛题的主控和无刷驱动主控方案都限定使用“灵动微电子”的MCU。逐飞科技作为灵动微电子的大学计划官方合作伙伴,在去年12月1日就发布了基于MM32的极速越野组BLDC开源项目,以此更好的支持广大参赛同学学习无刷电机控制技术,更好的做参赛准备。   同时逐飞基于灵动提供的两颗电机芯片都制作出了无刷驱动方案,一种方案是基于MM32SPIN360,一种方案是基于MM32SPIN27。于是就有了今天的开源项目发布:“逐飞基于灵动MM32SPIN27PS的无刷驱动开源项目”     无刷电机原理   无刷电机原理部分咱在这里就不再赘述了,新接触无刷电机或者想要再复习一下无刷电机旋转原理的同学可以看看上一篇灵动的无刷电机开源文章,再来一遍传送门:逐飞基于MM32的极速越野BLDC开源项目   SPIN27芯片介绍 2.1 芯片基本参数 本次开源的无刷驱动芯片使用灵动的MM32SPIN27PS作为控制芯片。   这款单片机特点如下: 使用高性能的 Arm® Cortex®-M0 为内核的 32 位微控制器。 最高工作频率可达 96MHz。 包含两个12 位的 ADC,采样速度高达 1MHz。 通用定时器5 个、针对电机控制的 PWM 高级定时器2 个。 UART 接口2 个、I2C 接口1 个、SPI 接口2 个。 针对无刷电机应用内置 3 个运放,3 个比较器。 2.2 芯片特点   2.2.1.PWM高级定时器1/8   该芯片的TIMER1与TIMER8定时器,可以直接输出三路PWM信号或者是三路互补的PWM信号,当是互补的PWM信号时可以设置死区,无刷电机的三个半桥通过我们有三种驱动方式。 方式一:上桥给PWM信号,下桥通过IO控制开启与关闭(逐飞本次开源项目即使用的这种方式)。 方式二:上桥通过IO控制开启与关闭,下桥给PWM信号。 方式三:上下桥都给PWM信号,但是需要注意的是上下桥的PWM信号必须是互补的,因为上下桥不能同时导通,否则出现电源与地短路的情况,由于MOS开关具有延时,所以互补PWM信号还必须设置死区,作用是当其中一个桥关闭之后要延时一段时间再打开另外一个桥,避免出现电源对地短路的情况。插入死区之后的互补PWM信号如下图所示(使用逻辑分析仪采集到的波形)。   2.2.2.单片机集成比较器   该芯片内置三个比较器,如果采用六步方波无传感器的方式驱动无刷电机,那么势必会用到过零检测来判断何时进行换相,内置了比较器也为无传感器控制无刷电机带来了更多的便捷。在使用霍尔有感的方式我们也可以使用比较器来实现自动(这里的自动表示无需代码干预即可实现)堵转保护等功能。   2.2.3.单片机集成运放   该芯片内置了三个运放,可以用于电流检测,使用磁场定向控制(FOC),或者检测线路电流从而判断是否堵转等故障出现,然后及时关闭控制避免硬件出现损坏。内置运放进一步简化了电路降低了制作的难度。   3.硬件原理图 由于单片机内部已经集成了运放、比较器、预驱,因此外围器件选择主要就集中在了MOS管型号的选择上,MOS管我们选择的型号是TPH1R403NL,这款MOS电流高达150A,10V的时候内阻低至1.2毫欧,开启电压低至2.5V左右,性价比较高,因为灵动的电机驱动专用芯片集成功能丰富,所以用它加上MOS就简单的构成了无刷电机驱动硬件方案。具体原理图部分可以看下图,图看不清不要紧,我们稍后会放在Gitee进行开源,下载PDF即可查看。       本次开源的灵动MM32SPIN27PS无刷驱动硬件部分与上次使用灵动MM32SPIN360C的硬件部分基本一致,仅更改了串口调试部分和信号输入输出端口,并且新增了晶振电路,其他部分则未作修改。   4 程序部分 4.1 灵动MM32SPIN27PS无刷驱动开源项目的源码 4.1.1.开源项目的工程目录结构 逐飞Infineon智能车BLDC开源项目的目录结构如下图所示。   CODE文件夹下放置的是逐飞科技精心编写的无刷电机驱动相关代码。 sdk是灵动官方的底层驱动,如果还需要其他的单片机片内外设功能,可以基于sdk文件下的底层自行编写程序实现。 zf_common、zf_driver和zf_device则是逐飞基于灵动MM32SPIN27PS制作的底层库。 user_c文件夹下放置的是主程序及中断文件。 4.1.2.无刷电机驱动需要用到的相关内外设          以及驱动代码   无刷电机需要用到的单片机片内外设有: ADC:主要用于检测电源电压、采集放大时候的母线电流以及相电流 高级定时器1:主要用于输出电机所需要用到的互补PWM信号,并且实现自动堵转保护,无需代码干预,当母线 电流超过设定值的时候,自动关闭定时器输出。 GPIO:主要用于LED指示灯,用于显示各种状态,并且初始化输出方向信息和速度信息的端口。 PWM输入:使用高级定时器8的输入捕获实现对外部PWM信号的周期以及占空比获取。 无刷电机的驱动文件有:bldc_config.h文件用于配置电机参数,例如是否开启闭环、是否开启刹车、最大转速设置。hall文件主要用于检测霍尔的值、换相时间计算、转速计算。motor文件主要用于电机占空比输出、速度计算、速度和方向信息输出。move_filter文件主要用于,对数据进行滑动平均滤波。pid文件主要用于对转速进行速度PID闭环。   4.1.3.主函数及中断函数说明   主函数与中断的文件存放在USER文件夹中,无刷电机控制部分由GTM模块硬件完成,所以并没有代码用于控制无刷电机,中断相关的函数全部放在了isr.c中。 4.2 MM32SPIN27PS无刷驱动开源项目的程序工作流程讲解 为了更清楚的表达起工作流程,整个项目的软件流程绘制了几张流程图,同时也加以文字说明。   4.2.1.主函数流程图     上图为本次开源驱动程序的主函数部分,不难看出来,与上次开源的360C主函数部分基本一致,主循环主要负责将当前电机和驱动板的状态通过LED灯输出,并且将部分电机参数发送到虚拟示波器,因此主函数并不执行电机控制的部分,控制部分通过ADC采集中断来触发。   4.2.2.ADC中断流程图   ADC中断是无刷电机的核心中断,ADC触发采集是由定时器1的通道4占空比更新事件进行触发的,因此ADC中断频率与TIMER1输出的PWM频率是一致的。PWM频率是40KHz,因此ADC的中断频率也是40KHz。   在中断内主要是获取母线电流、相电流、电源电压。母线电流在之后做电流环的时候需要使用到,也可以用于做故障检测,当检测到电流过大的时候,及时关闭输出以保护硬件,相电流可以用于之后做FOC驱动方案的时候提供支持。 扫描霍尔这个流程块中,主要是统计每次换相的时间,如果换相时间过长则认为出现故障此时应该及时关闭输出。当电机正常运行的时候将每次换相的时间都保存在数组内,当得到最近6次的换相时间之后,我们就能知道电机转动一圈所花费的时间,从而就能够计算出电机的转速了。在每次换相的时候更改速度输出引脚的PWM频率,这样外部控制器也能轻松的检测到电机的转速,而无需外加编码器。然后根据读取到的霍尔值计算出下次期望的霍尔值。 霍尔扫描结束之后,开始检查延时换相时间是否到,时间没有到则延时时间减一,延时时间为0的时候开始进行换相动作,这里延时换相的原因是因为在电机高速运转的时候霍尔有滞后导致的,可能有人问为什么霍尔滞后了,你还要延时换相呢?因为我们采用的方法是,当霍尔出现滞后之后,我们换相的时候并不是换到下一相,而是换到了下下相,这样就相当于超前换相了,所以我们需要加一定的延时去匹配,从而得到一个最佳的换相点。 4.2.3.定时器中断流程图 定时器3中断频率为1KHz,主要用于根据DIR引脚设置电机是正转还是反转,然后计算速度曲线,用于实现电机缓慢加速(此功能可关闭),缓慢加速降低电机加速时功率,在调试阶段可以尽量保护车模以及硬件电路。然后进行PI闭环调节,这里主要实现是将我们采集到的电机速度与设置的电机速度求差,将得到的偏差*系数KP得到比例输出Pout,然后对偏差*系数KI并将每次计算出的结果进行求和得到Iout,最终将Pout与Iout相加,然后将相加之后的和输出到占空比寄存器驱动电机运转。其中KP、KI系数可能需要自己再多多调试,以找到更加完美的参数,使得电机运行更加迅速且稳定。     定时器8中断主要作用是用来接收外部PWM信号的周期与高电平时间,然后计算信号的占空比,根据占空比的大小设置电机的转速,从而实现外部控制器来控制电机的转速。   5.逐飞制作的参考学习驱动板及无刷电机推荐   5.1 基于灵动MM32SPIN27的无刷电机驱动学习板使用简介   上图中1-8号标号的含义如下:   1、直流电源接口,使用12V电源供电,建议使用3S电池。 2、控制输入与信息输出端口,PWM引脚是速度调节端口,外部控制器输出PWM,通过调节占空比大小来调节速度。DIR引脚是用于设置电机转动方向的;SPDOUT与DIROUT引脚是输出电机转速信息的,电机转得越快此引脚上输出的信号频率越高,推荐使用单片机采集编码器的接口进行信息采集。SPDOUT连接编码器采集接口的A通道或者连接单片机的计数通道,DIROUT连接编码器采集接口的B通道或者连接方向引脚(具体可以参考编码器采集例程)。 3、SWD调试接口,可以对电机驱动上的单片机烧写程序以及在线调试。 4、无刷电机接口,接入无刷电机的A、B、C三相。 5、无刷电机霍尔接口,连接无刷电机霍尔接口。霍尔接口可通过淘宝搜索“ZH1.5 6P”找到 6、电机驱动使能开关,开关是连接到IO上,通过单片机硬件实现的使能。 7、电源LED灯,给驱动供电时此灯亮起。 8、使能LED灯,打开开关时此灯亮起。 9、运行LED灯,当无刷电机运行时此灯亮起。 10、错误指示LED灯,当无刷电机堵转时此灯亮起。 温馨提示:该驱动板成品仅供学习参考调试,不能直接将成品驱动使用在正式参赛的小车上,正式参赛的无刷电机驱动板需要同学们自行制作并按要求在铜层打上队伍信息。 如果你申请到的是灵动MM32SPIN360芯片,可以根据上一个基于灵动MCU的开源项目来制作自己的无刷电机驱动板,如果你申请到的芯片是灵动MM32SPIN27,可以参考此开源项目来制作自己的无刷电机驱动板。   5.2.无刷电机推荐   逐飞对很多款电机进行了测试,让其一家无刷电机的生厂商定制一款无刷电机供我们竞赛中使用,目前已在现货发售中,逐飞推荐极速越野组使用这款无刷电机,逐飞的开源项目代码和硬件也是以这款电机为样品来进行测试的。 这款电机的参数如下:有感、三槽两极、2860Kv(Kv表示每增加一伏电压电机增加的转速,最高12V)、尺寸36(mm)*50(mm)、额定功率190W、支持1-3S锂电池供电。   逐飞无刷电机   逐飞无刷电机与驱动接线示意图 温馨提示:此款电机仅为逐飞推荐款,同学们也可以选择自己认为合适的无刷电机,这一点上规则是没有限制的,但建议大家选择有感无刷。   6.总结 最后,上开源项目gitee链接: https://gitee.com/seekfree/MM32SPIN27_BLDC_Project   打包下载开源库压缩包,就可以愉快的开始玩无刷啦。 逐飞会对本开源项目进行持续更新和维护,预计功能上还会继续添加串级闭环的功能,速度环作为外环,电流环作为内环,刹车力度可调节,这样可以不需要曲线计算即可实现电机缓慢加速的功能,通过内部电流环限定电流大小也能更好的保护硬件电路。之后也会尝试使用FOC方案驱动电机。当然,对这些功能有兴趣的同学可以自己提前研究尝试一下。 灵动的电机专家告诉你,这些东西完全搞明白之后,都足够找一份相对不错的工作了。 特别说明:该开源项目仅用于各参赛同学在设计自己的小车时进行参考,硬件和软件都不能够直接拷贝使用在自己的作品中,请大家参考后重新完成硬件和软件的设计制作。 推荐款无刷电机、无刷驱动学习板及越野组学习套件已上架逐飞淘宝店(seekfree.taobao.com),如果开源项目中有任何BUG,欢迎留言反馈。  

  • 2022-04-30
  • 发表了主题帖: 乐鑫ESP8266 GPIO 电平状态是什么?

    除 XPD_DCDC 外,其他 GPIO 均可配置为高电平。 GPIO开机后默认电平状态为:除6个SDIO+GPIO4+GPIO5+GPIO16外,其余GPIO均内置上拉电阻。要下拉 GPIO,需要外部下拉或反相电路。 注意:GPIO 的外部电压电平不能为 5V。GPIO4/5 不能用外部 1M 电阻上拉。请改用 100K 电阻。  

  • 发表了主题帖: 如何启用 UART 流控制?

    UART 通信数据格式的配置请参考SDK/driver_lib/driver/中的uart.c文件。 在 UART 通信中配置硬件流控的两个步骤如下: (1) 在 uart.h中将以下属性设置为 1 : #define UART_HW_RTS  1 //set 1: enable UART hw flow control RTS, PIN MTDO, FOR  UART0 #define UART_HW_CTS  1  //set1: enable uart hw flow control CTS , PIN MTCK, FOR  UART0     (2) 配置硬件流控阈值。 硬件流控制的阈值在以下屏幕截图中以红色方块突出显示。当 RXFIFO 中的字节数大于 110 时,RTS 将被拉至逻辑高电平。  

  • 发表了主题帖: 乐鑫ESP8266 将如何与云服务器通信?

    标准 HTTP 协议可用于连接到更新服务器。例如,当您的自定义服务器正在运行时,当 ESP8266 设备启动套接字并发送 HTTP 请求时:   GET /your-bin-file-path.bin HTTP/1.1 主机:yourdomain.com 连接:keep-alive 缓存控制:max-age=0 接受: text/html,application/xhtml+xml,application/xml;q =0.9,image/webp,*/*;q=0.8 用户代理: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,ja;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2   请注意,HTTP 协议规定请求以“ \r\n\r\n ”结尾,因此请不要在整个请求短语之间使用此组合。

  • 回复了主题帖: ISM330DHCX有限状态机学习资料

    ISM330DHCX有限状态机与它的那个iNEMO惯性SiP模块有什么不同

  • 2022-04-13
  • 发表了主题帖: 问一下能支持RISC-V的集成开发环境有哪些?

    问一下:最近比较迷茫,能支持RISC-V的集成开发环境有哪些?你用的是什么,那种比较好用或者值得推荐

  • 2022-04-11
  • 回复了主题帖: 【AT-START-F425测评】+ UART串行通讯及应用

    所说能实现双串口间的转换性通信,能通讯过程中实现数据格式的转换和双方不同波特率的对接,指在一个MCU上能实现?

  • 2022-04-10
  • 回复了主题帖: SparkRoad测评(4)-组合电路与latch测试

    原来检验安路软件对latch的探测能力是这样搞的,谢谢

  • 发表了主题帖: 乐鑫ESP8685技术规格书

    乐鑫ESP8685技术规格书      

  • 2022-04-08
  • 发表了主题帖: 基于中颖SH32F205的变频空调室外机控制系统

        SH32F205主要特性 内核:32位ARM Cortex-M3 120MHz工作频率,核心代码可加载至C-RAM全速运行 提供Pre-fetch指令预取和I-Catch跳转指令、D-Catch数据文字池缓存功能 集成数学运算协处理器(MACP) 硬件CORDIC协处理器,支持三角运算和坐标变换 硬件IQ除法器,支持64/32除法运算 电机专用SVPWM引擎,支持五段式和七段式两种模式 存储器 最高256K字节FLASH程序存储器 8K字节SRAM+16K字节C-RAM(可作为Code Ram或DataRam) 时钟、复位和电源管理 2.4V~5.5V单电源供电 上电复位(POR)、掉电检测(BOD)、低电压复位(LVR) 硬件独立看门狗(IWDT)、窗口看门狗(WWDT) 内嵌8MHz RC振荡器,和内置PLL配合,可实现主时钟常温0.2%/全温度范围1%精度 支持外置4M~16MHz晶体振荡器/陶瓷振荡器 时钟安全监控(CSM) 3个独立的12位高速模数转换器(ADC1/ADC2/ADC3),2M SPS最高采样速率 1个DMA控制器,8个独立的DMA通道,支持内存到内存、内存到外设、外设到内存传输 最多79个快速GPIO端口,任何一个GPIO都可映射为外部中断输入 2个专用电机控制模块(MCM1/MCM2) 提供2套6路PWM输出,16位分辨率,支持互补或独立模式,输出极性可单独控制 支持单次计数模式,边沿对齐模式,中心对齐模式,带死区产生逻辑及故障自动检测功能 PWM周期内可设置多个时刻硬件触发ADC功能,支持MCM同步输出、硬件相移和逐波限流功能 4个16位通用PWM定时器(GPT0/GPT1/GPT2/GPT3) 4个16位基本定时器/计数器(TIM5/TIM6/TIM7/TIM8) 通信接口 3个通用异步串行口(UART1/2/3) 2个独立串行外设接口(SPI1/2) 1个独立两线串行接口(TWI) 丰富的片上模拟模块(AMOC) 3个高带宽模拟放大器 3个高速模拟比较器 内部温度传感器,支持校准操作 内部基准源,可作为ADC转换基准,也可产生多级比较基准电平 CRC代码校验、CRC数据传输校验;SRAM的March-C/March-X检测算法 96位芯片唯一识别码 标准SWJ烧写/仿真接口 工作环境温度:-40℃~+105℃   名称 描述 压缩机类型 PMSM永磁同步电机 驱动方式 无传感器矢量控制 功率范围 <=3P 电压适应性 100-265V  50/60Hz 频率范围 8-200Hz 载波范围 5-9K 电流采样方式 三电阻采样、单电阻采样 PFC 有源PFC,载频14-40K,额定功率时功率因数>0.99 PMSM外风机 内置驱动无感矢量控制/外置驱动 保护功能 电压、电流、温度、过载、IPM、PFC 其他功能 低频补偿、弱磁、最优电流、死区补偿、逆风启动、膨胀阀   SH32F205框图       硬件系统—主芯片   PMSM无传感器矢量控制   全维状态观测器—状态方程     全维状态观测器—自适应观测器     低频振动抑制-前馈电流补偿   低频补偿方案—机械角度(两对极)     低频补偿方案—控制流程     低频补偿方案—自动补偿     低频振动数据     低频电流波形-10Hz     单电阻采样方案—移相     单电阻采样方案—控制流程     单电阻采样电流波形   弱磁方案实现     最优电流方案实现     死区补偿方案实现     压缩机三相电流波形-60Hz     压缩机三相电流波形-90Hz   压缩机控制波形-启动   压缩机控制波形-负载突变   有源PFC功率因数校正   PFC方案实现1     PFC方案实现2     交流输入侧波形(PFC)     交流输入侧波形(电压突变)     直流风机电流波形       集成直流风机控制方案     电子膨胀阀控制—步进电机控制方案 使用MCU的四个I/O口实现步进电机的四相八拍控制,无需细分; 驱动部分使用ULN2003,提升驱动能力     保护与安全策略 降频 调制度保护--输出电压超出逆变器最大电压 过转矩保护--负载转矩超出最大转矩范围 报警停机 失速保护—转速高,Iq控制到0 失控保护—反馈转速和实际转速差值大 堵转保护—观测器无输出,失步 短路保护—IPM模块保护 过流过压保护 温度保护   控制板实物图     空调实验室测试环境     谢谢关注,如有疑问可致电0755-25181447!

  • 2022-04-01
  • 回复了主题帖: 【平头哥RVB2601创意应用开发】+webplay Demo试用及源码分析

    所绑定的回调函数network_event也在app_main中,还需要通过事件ID,需要找到什么网络操作,感觉有点麻烦

  • 回复了主题帖: 【沁恒RISC-V内核 CH582】移植射频代码02

    把CH582驱动RFID讲的很细致了 楼主玩沁恒RISC-V内核的MCU还是很顺溜的,跟着楼主学习

  • 2022-03-28
  • 回复了主题帖: 【米尔MYC-JX8MPQ评测】+ 运行 TensorFlow Lite(CPU和NPU对比)

    除了NPU运行要比CPU快很多,还有很多优点

  • 回复了主题帖: 【AT-START-F425测评】AT32F425尚无法用RT_T创建工程

    看来AT-START-F425开发板支持RT_T来构建其开发环境的说法,还需要仔细研究一下

  • 2022-03-24
  • 回复了主题帖: 【平头哥RVB2601开发板试用体验】 GPIO输出测试

    下面准备测什么呢

  • 回复了主题帖: 【AT-START-F425测评】初品AT32F425

    还是挺给力的,AT-START-F425能是支持Keil, IAR, eclipse, RT-Thread Studio等IDE,不错

  • 2022-03-21
  • 发表了主题帖: 推荐CH579M的开发目录

    本帖最后由 火辣西米秀 于 2022-3-21 07:30 编辑 CH579M开发笔记——目录   一、预备知识:芯片特性介绍,开发工具安装 1.1.1 CH579M芯片介绍 1.1.2 Keil软件的安装和使用 1.1.3 CH579M程序下载   二、基础例程:基本外设使用,常用功能讲解 2.1.1 CH579M:GPIO输出,点亮LED 2.1.2 CH579M:GPIO输入,按键检测 2.1.3 CH579M:GPIO输入,中断检测 2.2.1 CH579M:定时器使用 2.2.2 CH579M:红外遥控 2.2.3 CH579M:定时器实现时间片编程 2.3.1 CH579M:UART数据收发 2.3.2 CH579M:UART数据收发(485通信方式) 2.3.3 CH579M:UART数据收发(超时判断+状态机) 2.3.4 CH579M:UART数据收发(环形队列) 2.4.1 CH579M:I2C读取温湿度传感器AHT10 2.4.2 CH579M:I2C驱动TM1650点亮4位数码管 2.4.3 CH579M:I2C驱动OLED屏幕显示 2.5.1 CH579M:ADC通过NTC热敏电阻测量温度 2.6.1 CH579M:SPI驱动RC522 RFID刷卡模块 2.7.1 CH579M:内部FLASH读写测试   三、进阶例程:高级外设使用,常用模块驱动 3.1.1 CH579M:Ethenet网口基础知识讲解 3.1.2 CH579M:Ethenet网口连接TCP服务器 3.1.3 CH579M:Ethenet网口连接UDP服务器 3.1.4 CH579M:Ethenet网口连接MQTT服务器 3.1.5 CH579M:Ethenet网口↔串口透传 3.2.1 CH579M:BLE蓝牙基础知识讲解 3.2.2CH579M:BLE蓝牙普通外设 3.2.3 CH579M:BLE蓝牙HID键盘 3.2.4 CH579M:BLE蓝牙心率监测 3.2.5 CH579M:BLE蓝牙↔透传 3.2.6 CH579M:BLE蓝牙低功耗应用   四、实战综合:实战项目讲解,综合功能运用 4.1.1 CH579M:基于ADC功能的温度控制器 4.1.2 CH579M:基于AHT10的温湿度远程采集 4.2.1 CH579M:基于以太网和串口的透传DTU 4.2.2 CH579M:基于以太网的远程控制开关

  • 2022-03-17
  • 发表了主题帖: 基于MM32与M26物联网入门:远程呼叫及开锁

    应用场景 适用于庭院大门,当有来客呼叫时,实现手动开锁、远程开锁的功能;   应用功能 通过MM32主控芯片与M26 2G通讯模块与远程服务器进行连接,当有访客按下CALL按键时,本地响应门铃(本应用暂未接门铃),同时进行远程呼叫;户主可以通过OPEN按键直接给访客开门,也可以通过服务器发送OPEN指令进行远程开门;   在没有访客呼叫时,MM32与服务器之间每间隔10秒钟进行一次心跳包传输,以保证与服务器之间SOCKET链路的连接;   在有访客呼叫时,若没有进行开锁动作,则每间隔3秒钟向服务器端发送一个呼叫指令;当接收到服务器端OPEN开锁命令时,执行开锁动作,开锁时间保持3秒钟,开销期间并向服务器反馈开锁是否成功的状态;   硬件模块 在网上淘到一块基于M26的2G通讯板,将主控MCU替换成MM32F0273D6P,这样省去了通讯板的设计及绘制,因为之前做过不少的工业远程控制项目,所以对通讯板的原理、控制都已经很熟悉了;通讯板如下图所示,带有5个接口及一个用户自己定义按键:1路光耦输出控制、2路带极性的光耦输入采集、1路无极性的光耦输入采集、以及1个UART程序烧录接口;   对硬件设计进行分析后,正好满足我们当前的硬件需求:1路光耦输出控制用于门锁的控制、2路带极性的光耦输入采集用于手动开锁按键和门外的呼叫按键、最后1路无极性的光耦输入采集则用于门锁的开关状态检测(我们选用的电磁锁是带有开关状态输出的);   为什么选用MM32F0273D6P这个芯片呢?基于通讯板,我们需要一个LQFP48封装的芯片,其次MM32F0273D6P是一个32位的Cortex-M0的控制芯片,最高工作主频可达到96MHz,运行速度够快;带有128KB FLASH程序存储空间,以及16KB SRAM的运行内存,能够满足在物联网工程项目功能上的应用;最后就是通讯板是通过UART下载程序的,MM32F0273D6P出厂自带了ISP功能,可以通过BOOT引脚来选择启动程序,配合上位机软件实现程序的烧录。   原理图设计 除了通讯板之外,我们还需要另外一块硬件单板配合演示/调试,功能如下:2个按键(1个手动开锁按键、1个门外呼叫按键)、1个门锁开关控制电路(继电器控制方式)、1个门锁开关状态检测电路(用于检测门锁的开关状态,以及确认门锁控制是否正常),最后就是开发板的供电(5V)以及门锁供电(12V);原理图如下所示:   PCB设计3D效果图   整机实物图   功能实现代码:按键检测及处理 复制 /******************************************************************************* * [url=home.php?mod=space&uid=159083]@brief [/url]       * @param       * @retval       * [url=home.php?mod=space&uid=1020061]@attention [/url]    *******************************************************************************/ void KEY_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, char *Name) {     if(*State == 0)     {         if(Value == Bit_RESET) *Count += 1;         else                   *Count  = 0;         if(*Count > 5)         {             *Count = 0; *State = 1;             printf("\r\n%s Pressed", Name);             if(strcmp(Name, "OPEN") == 0)             {                 BSP_LOCK_Control(LOCK_MODE_MANUAL, ENABLE);                 if(RemoteState != 0)                 {                     RemoteState = 0;                     M26_SendMessage("Manual Open The Door!");                 }             }         }     }     else     {         if(Value != Bit_RESET) *Count += 1;         else                   *Count  = 0;         if(*Count > 5)         {             *Count = 0; *State = 0;             printf("\r\n%s Release", Name);             if(strcmp(Name, "OPEN") == 0)             {                 BSP_LOCK_Control(LOCK_MODE_MANUAL, DISABLE);             }             else if(strcmp(Name, "CALL") == 0)             {                 if(RemoteState == 0)                 {                     RemoteState = 1;                     M26_SendMessage("Calling...");                 }             }         }     } } /******************************************************************************* * @brief       * @param       * @retval       * @Attention    *******************************************************************************/ void KEY_Scan(void) {     static uint8_t KeyState[3] = {0, 0, 0};     static uint8_t KeyCount[3] = {0, 0, 0};     KEY_SubScan(&KeyState[0], &KeyCount[0], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11), "KEY");     KEY_SubScan(&KeyState[1], &KeyCount[1], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8), "CALL");     KEY_SubScan(&KeyState[2], &KeyCount[2], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4), "OPEN"); }   功能实现代码:M26启动及配置 复制 uint8_t  M26_Buffer[1000]; uint16_t M26_Length  =  0; /******************************************************************************* * @brief       * @param       * @retval       * @Attention    *******************************************************************************/ void M26_InitBuffer(void) {     M26_Length = 0;     memset(M26_Buffer, 0, sizeof(M26_Buffer)); } /******************************************************************************* * @brief       * @param       * @retval       * @Attention    *******************************************************************************/ void M26_SendData(uint8_t Data) {     UART_SendData(UART2, Data);     while(UART_GetFlagStatus(UART2, UART_IT_TXIEN) == RESET); } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void M26_SendString(char *str) {     while(*str)     {         M26_SendData(*str++);     } } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ uint32_t M26_AT_WaitForReply(char *Keyword, uint32_t Timeout) {     M26_InitBuffer();     while(Timeout--)     {         if(QUEUE_EMPTY(QUEUE_M26_RX_IDX) == 0)         {             M26_Buffer[M26_Length++] = QUEUE_READ(QUEUE_M26_RX_IDX);             if(strstr((char *)M26_Buffer, Keyword) != NULL)             {                 printf("\r\n%s", (char *)M26_Buffer);break;             }         }         SysTick_DelayMS(1);     }     return Timeout; } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ uint32_t M26_AT_SendCommand(char *Command, char *Response, uint32_t Timeout) {     if(Command != NULL)     {         M26_SendString(Command);         M26_SendString("\r\n");     }     if(Timeout != 0)     {         return (Timeout - M26_AT_WaitForReply(Response, Timeout));     }     else     {         return 1;     } } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void M26_SendMessage(char *str) {     char Buffer[200];     memset(Buffer, 0, sizeof(Buffer));     sprintf(Buffer, "AT+QISEND=0,%d", strlen(str));     M26_AT_SendCommand(Buffer, ">", 1000);     M26_SendString(str);     printf("\t%dms", M26_AT_SendCommand(NULL, "SEND OK", 1000)); } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void M26_AT_Startup(void) {     printf("\t%dms", M26_AT_SendCommand(NULL, "RDY",          10000));     printf("\t%dms", M26_AT_SendCommand(NULL, "+CFUN: 1",     10000));     printf("\t%dms", M26_AT_SendCommand(NULL, "+CPIN: READY", 10000));     printf("\t%dms", M26_AT_SendCommand(NULL, "Call Ready",   10000));     printf("\t%dms", M26_AT_SendCommand(NULL, "SMS Ready",    10000));     printf("\t%dms", M26_AT_SendCommand("AT", "OK",           10000));     while(M26_AT_SendCommand("AT+CSQ", "OK", 500) != 0)     {         if(strstr((char *)M26_Buffer, "99,99") == NULL)         {             break;         }         SysTick_DelayMS(500);     }     M26_AT_SendCommand("AT+CCID",   "OK", 500);     M26_AT_SendCommand("AT+COPS?",  "OK", 500);     M26_AT_SendCommand("AT+CREG?",  "OK", 500);     M26_AT_SendCommand("AT+CGATT?", "OK", 500);     M26_AT_SendCommand("AT+QIFGCNT=0", "OK", 500);     M26_AT_SendCommand("AT+QICSGP=1,\"CMMTM\"", "OK", 500);     M26_AT_SendCommand("AT+QIDNSIP=1", "OK", 500);     M26_AT_SendCommand("AT+QIMUX=1", "OK", 500);     M26_AT_SendCommand("AT+QIOPEN=0,\"TCP\",\"xld0932.xicp.net\",10520", NULL, 0);     printf("\t%dms", M26_AT_SendCommand(NULL, "CONNECT OK", 20000)); }   功能实现代码:呼叫及开锁控制 复制 /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void BSP_LOCK_Control(uint8_t Mode, uint8_t Enable) {     LockMode = Mode;     if(Enable == 0)     {         GPIO_WriteBit(GPIOA, GPIO_Pin_6, Bit_SET);      /* 上锁 */     }     else     {         GPIO_WriteBit(GPIOA, GPIO_Pin_6, Bit_RESET);    /* 开锁 */     } } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void BSP_LOCK_Handler(void) {     static uint8_t LockTimeout = 0;     if(LockMode == LOCK_MODE_REMOTE)     {         LockTimeout++;         if(LockTimeout == 15)         {             if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5))             {                 M26_SendMessage("Open The Door Failure!!!");             }             else             {                 M26_SendMessage("Open The Door Successfully!");             }         }         if(LockTimeout >= 30)         {             RemoteState = 0;             BSP_LOCK_Control(LOCK_MODE_MANUAL, DISABLE);         }     }     else     {         LockTimeout = 0;     } } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void REMOTE_Handler(void) {     if(RemoteState == 0)     {         if(RemoteHeartbeat++ >= 100)         {             RemoteHeartbeat = 0;             M26_SendMessage("Alive!!!");         }     }     if(RemoteState == 1)     {         RemoteCount++;         if(RemoteCount >= 30)         {             RemoteCount = 0;             M26_SendMessage("Calling...");         }     }     else     {         RemoteCount = 0;     } } /******************************************************************************* * @brief       * @param       * @retval       * @attention    *******************************************************************************/ void MESSAGE_Handler(void) {     if(QUEUE_EMPTY(QUEUE_M26_RX_IDX) == 0)     {         MSG_Buffer[MSG_Length++] = QUEUE_READ(QUEUE_M26_RX_IDX);         /* 远程开锁控制 & 返回开锁成功或失败 */         if(strstr((char *)MSG_Buffer, "OPEN") != NULL)         {             RemoteState = 2;             BSP_LOCK_Control(LOCK_MODE_REMOTE, ENABLE);             MSG_Length = 0;             memset(MSG_Buffer, 0, sizeof(MSG_Buffer));         }     } }     演示效果 服务器我们使用花生壳内网穿透映射的方式,将域名及端口号映射到本地内网的IP和端口,再使用网络调试助手软件建立一个TCP/IP服务器,来进行演示,如下图:   ISP下载程序   系统启动&M26初始化配置   呼叫后手动开锁   呼叫后远程开锁  

统计信息

已有126人来访过

  • 芯积分:1104
  • 好友:--
  • 主题:722
  • 回复:308
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言