| | | | | 这是5318的参数介绍
IP5318:I-Q3.0/2.0、I-P、TYPE-C快充IC电性参数如下:
(一)快充标准全支持
支持I-Qcharger3.0/2.0 快充输出标准
支持I-Pcharger快充标准
支持Type-C 快充标准
(二)全集成、低成本
单电感快速充电放电架构、集成功率MOS
集成I-Qcharger输出、I-Pcharger快充、Type-C、BC1.2等通讯协议
集成Type-C充电放电控制
(三)快充充电
5A快速充电,支持5V至12V高压快充输入,自动匹配适配器
支持I-Pcharger快充,3A@5V、2A@7V、2A@9V、1.5A@12V自动匹配;
支持Type-C 3A@5V、2A@9V、1.5A@12V快速充电
(四)快充放电
快速放电: 3A@5V、2A@7V、2A@9V、1.5A@12V
Type-C快速放电: 3A@5V、2A@9V、1.5A@12V
Android 和apple 手机自动匹配
(五)高可靠性和灵活性
28V 输入、输出耐压,11重保护
集成14Bit ADC,集成Fuel Guage 电量计算法,支持I2C通讯
封装:QFN40
|
|
|
| | | | | | | 这是1351的资料 SMB1351
是一款支持Quick Charge 2.0(QC 2.0)快速充电协议的充电接口控制器IC,可自动识别充 电设备类型.
SMB1351
并通过充电协议与设备握手,使之获得 设备允许的安全最高充电电压,在保护充电设备的前 提下节省充电时间。 特点 l 完全支持 Quick Charge 2.0 规范 v A类:5V、9V及12V输出电压 v B类:5V、9V、12V及20V输出电压 v 可选12V或20V输出限制 l 兼容USB充电规范1.2 v 支持USB充电规范DCP模式 v 默认5V模式工作 l 待机功耗低 v 5 V输出电压时低于350uW l 可靠的保护功能 v 引脚间短路保护 v 引脚开路保护及电路故障保护
|
|
|
|
| | | | | | | | | | | QC快充采用高压的方式充电,到电池端变成大电流,损耗较大发热也厉害,PD协议现在最新的快充技术,不是太懂
|
|
|
| | | YTDFWANGWEI- 积分:109774
- |
- 主题:142
- |
- 帖子:45909
积分:109774 版主 | | | | 快充慢充可以理解,是为了给动力电池充电,那么这个放电功能是为了什么功能设计的呢?
|
|
|
|
| | | | | | | | | | | 在这里主要就是快充功能,快放需要支持QC3.0协议才可以
|
|
|
| | | | | | | | | 其实这个快放功能对于小车不起作用,除非支持QC3.0协议,才能握手成功实现快放
|
|
|
|
|
|
|
| | | | | | | | | | | | | 暂时没做这块,无线充电的话可以用ti的BQ系列的方案很成熟的
|
|
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 程序这块主要就是wifi和视频这块,第一次尝试,后期会整理
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | 线圈是用来感应电的,就是线圈之间产生的磁场来传输电能的 |
|
|
|
| | | | | | | | | | | | | | | | | | | | | 具体损耗不知道多大,这是基本的原理
无线充电系统主要采用电磁感应原理,通过线圈进行能量耦合实现能量的传递。系统工作时输入端将交流市电经全桥整流电路变换成直 流电,或用24V直流电端直接为系统供电。经过电源管理模块后输出的直流电通过2M有源晶振逆变转换成高频交流电供给初级绕组。通过2个电感线圈耦合能 量,次级线圈输出的电流经接受转换电路变化成直流电为电池充电。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | |
现在正在确定wifi小车的初步方案,网上通过视频传输的都是用无线路由器实现的,用wifi模块不知道可行。是数据传输速度不行吗,
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 用福禄克的钳形表测得结果,比较准确,其实快充的根本还是提高电池的充电电流,只不过在输入端提高电压的方式来降低电路的损耗,
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 楼主,你用的锂电池没有保护板吗?保护也不可能提供这么大的电流呀
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | |
这是板子的背面,应该明白了吧,保护板在背面做的,实际上电流也不算大,您可以算一下,这是5节电池并联10000ma,如果0.5C充电的话电流是5A,现在是0.4C充电
|
|
|
|
|
|
| | | | | | | | | ANDROID APP开始写了没有?你是准备远程还是局域网?
串口WIFI模块做视频传输怕是不行的,最小要30帧/S才算能用的,在手机端H264解码就能刷到VIEW上显示了
|
|
|
| | | | | | | | | | | 最好是可以远程,30帧可以了,分辨率不高,能达到720P不错了,串口wifi模块内存大的应该可以吧 |
|
|
| | | | | | | | | | | | | APP这块不会写啊,java开发吧,现在正在学习,
|
|
|
| | | | | | | | | | | | | | | 我是用JAVA开发的,不过现在出了新的语言,远程视频不好整的! |
|
|
|
| | | | | | | | | | | | | | | | | | | app透过服务器向单片机发指令,如果是局域网的话可以直接用手机和工作在AP状态下的WIFI模块建立UDP通信,然后向MCU发指令
|
|
|
| | | | | | | | | | | | | | | | | | | | | 就是这个指令的协议是谁定的啊,不如帧头 帧尾 数据
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | app界面倒也不是太难,云台控制,开启视频,小车的前后左右,但是自己开发没基础就难了
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 电池的充放电电路自备,底盘 四个减速电机 ** 舵机 主控板 电机驱动板 超声波测距模块 wifi数传模块
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 这个协议是自由通信协议,先定义好,双方根据协议去解析就是了
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | 先做出来个不用APP让他自己平衡的车出来,**的功能可以后面加上的 |
|
|
| | | | | | | | | | | | | | | | | | | 平衡小车需要配件啊,硬件部分包括车模设计、电机以及驱动、传感器(加速度传感器、陀螺仪等)、以及MCU核心处理模块;软件部分主要是对传感器数据的处理算法和电机驱动方法,
|
|
|
| | | | | | | | | | | | | | | | | | | | | 主要就是通过姿态传感器(常用的MPU6050)输出数字信号给MCU,控制电机的正反转和速度来保持平衡,涉及到一些算法,比如PID等,后续有时间大家可以共同学习
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | MPU6050六轴加速度陀螺仪模块角度传感器自平衡车四轴姿态传感器
|
|
|
| | | | | | | | | | | | | | | | | 我也期待小车是个啥样子,主要是程序这块需要琢磨琢磨
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 不好意思,今天一不小心发现77楼当时的组装错误,有一个电机的接线朝外了,四个电机的接线都朝内,并且左侧两个电机一组,右侧两个电机一组,一定要注意接线,具体怎么左右转动后续程序中介绍
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 控制模块打算用stm32F103系列的单片机负责接收指令并控制电机,下面需要对wifi模块刷openwrt系统 |
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 目前用超声波来测距,就是通过确定和障碍物的距离,比如探头感应到距离10cm,小车就停止 |
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 其实智能家居这块源于物联网的兴起,主要有五种通信方式:Zigbee,Z-wave,433,315,wifi,蓝牙,比较常用的wifi和蓝牙较多,蓝牙的低功耗和wifi的远程监控特点在好多消费类电子设备运用很多,比如蓝牙音响,wifi插座,wifi**等等
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 简单介绍一下ESP8266模块,三种工作模式:Station 模式,AP 模式和AP 兼 Station 模式;有玩过路由器的应该知道路由器除了正常使用(AP模式)外,还可以接收其他路由器的信号(Station 模式),然后再发出来(AP 兼 Station 模式),都可以通过usb转ttl工具把8266脑连接,通过串口助手发送AT指令,但是要注意引脚的高低电平,还有串口助手选择好波特率 发送新行打钩,这是基本的配置http://www.cnblogs.com/yangfengwu/p/5205570.html,要通过wifi远程控制的话,需要与服务器连接,比如现在都是云服务器,机智云等,需要刷相应的固件SDK,工具比较多NodeMcu,网上教程和资料挺多的,可以学习一下
|
|
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 先介绍一下OpenWrt系统
openwrt是嵌入式设备上运行的linux系统。
OpenWrt 的文件系统是可写的,开发者无需在每一次修改后重新编译,
令它更像一个小型的 Linux 电脑系统,也加快了开发速度。
你会发现无论是 ARM, PowerPC 或 MIPS 的处理器,都有很好的支持。
并且附带3000左右的软件包,用户可以方便的自定义功能来制作固件。
也可以方便的移植各类功能到openwrt下。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | wifi数传模块是基于MIPS 24K 高通CPU的一款WIFI1X1芯片AR9331,其SDK采用uboot作为引导。是基于MIPS 架构的,目前有x86、ARM和MIPS三种主流芯片架构,
ARM指令集架构的主要特点:一是体积小、低功耗、低成本、高性能;二是大量使用寄存器且大多数数据操作都在寄存器中完成,指令执行速度更快;三是寻址方式灵活简单,执行效率高;四是指令长度固定,可通过多流水线方式提高处理效率。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 共同学习一下这三种架构的不同
MIPS是高效精简指令集计算机体系结构中的一种,与当前商业化最成功的ARM架构相比,MIPS的优势主要有五点:一是早于ARM支持64bit指令和操作,截至目前MIPS已面向高中低端市场先后发布了P5600系列、I6400系列和M5100系列64位处理器架构,其中P5600、I6400单核性能分别达到3.5和3.0DMIPS/MHz,即单核每秒可处理350万条和300万条指令,超过ARM Cortex-A53 230万条/秒的处理速度;二是MIPS有专门的除法器,可以执行除法指令;三是MIPS的内核寄存器比ARM多一倍,在同样的性能下MIPS的功耗会比ARM更低,同样功耗下性能比ARM更高;四是MIPS指令比ARM稍微多一些,执行部分运算更为灵活;五是MIPS在架构授权方面更为开放,允许授权商自行更改设计,如更多核的设计。
x86 CISC是一种为了便于编程和提高记忆体访问效率的芯片设计体系,包括两大主要特点:一是使用微代码,指令集可以直接在微代码记忆体里执行,新设计的处理器,只需增加较少的电晶体就可以执行同样的指令集,也可以很快地编写新的指令集程式;二是拥有庞大的指令集,x86拥有包括双运算元格式、寄存器到寄存器、寄存器到记忆体以及记忆体到寄存器的多种指令类型,为实现复杂操作,微处理器除向程序员提供类似各种寄存器和机器指令功能外,还通过存于只读存储器(ROM)中的微程序来实现极强的功能,微处理器在分析完每一条指令之后执行一系列初级指令运算来完成所需的功能。
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 固件刷完后更新有关stm32F103方面的程序和资料
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 在stm32当中L系列做的功耗非常低比如L476,都是STM官网推出的Nucleo系列开发板,而且板载下载调试器啊非常方便
学习的话用这款挺不错的
还有一款32引脚的L031,
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我们平时用的M3内核的较多,不过那个L476是M4内核的,上面都是些低功耗的而F4系列。比如入门级的F401,功能强大的,主频高的F413作为目前F4系列当中片上SRAM容量最高
作为我们平时学习用只做参考,还有好多开发板都可以,比如原子和野火的
|
|
|
| | | | | | | | | | | | | | | 确实很牛啊 组装完成了没有啊 无线小车适用很广泛啊 希望楼主继续分享 好好 学习一下。
|
|
|
| | | | | | | | | | | | | | | | | 初步功能已经完成,您可以看一下录的一段视频咋样,您看有没有其他功能不错,可以尝试加上去
|
|
|
| | | | | | | | | | | 您是做app ,有个eclipe啥软件是编程app 吗
|
|
|
| | | | | | | | | | | | | Eclipse是著名的跨平台的自由集成开发环境(IDE),和我们平时用的keil一样的,是用JAVA语言开发的
|
|
|
| | | | | | | | | | | 你好,视频传输这块每秒20帧可以吗我刚学习上位机软件这块,需要对拍照进行云点测试?不是太懂,小白求教
|
|
|
|
|
| | | | | | | | | 简单介绍一下wifi数传模块怎么刷机,首先通过USB口给设备供电,通过miniUSB口加上usb转网口网线连接电脑准备刷机工具
TFTP服务端:tftp32 就是局域网内可以传文件,
超级终端:putty Telnet、SSH、rlogin、纯TCP以及串行接口连接软件
需要相应的固件
具体教程http://www.wifi-robots.com/thread-108-1-1.html
|
|
|
| | | | | | | | | | | 下面的更新主要针对stm32方面的资料,小车的程序正在完善,会针对每个模块的相关资料和程序讲解一下
|
|
|
| | | | | | | | | | | | | 首先我们先了解一下单片机,一颗单片机由中央处理单元(CPU)、程序存储器(ROM)、数据存储器(RAM)、外设等单元组成,我们经常说的内核,就是指的CPU内核,比如传统的51内核 、ARM、X86、x64等 51单片机运用的非常多,上学时用的89C51,主要是对寄存器进行操作,还有经常用的PIC,AVR,不过现在STC的增强型单片机也非常不错,功耗也比较低,但是和目前流行的ARM内核的STM32还有一定的差距,主要区别如下: 1,STM32的工作频率可以倍频到72M,而C51单片机的频率一般不宜超过24M 2,STM32单片机的RAM和ROM及FLASH存储空间比C51单片机的要大几十倍 3,相比于51单片机,STM32F103系列提供的外设也更加丰富,如CAN接口、USB接口等。 特别是在一些数据处理和操作系统上面32更占优势
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | 对于STM32,我刚开始接触的是STM8,是个8位的单片机,具有3级流水线的哈佛结构,当时用的是STM8L。超低功耗的,支持ST-link在线调试意法半导体的超低功耗产品线支持多种对功耗极为敏感的应用,例如便携式设备。STM8L基于8位STM8内核,与STM32L系列一样采用了专有超低漏电流工艺,利用最低功耗模式实现了超低功耗(0.30 uA)。 STM8L系列包括4个不同的产品线,适于需要特别注意节约功耗的应用。功能定时器,AD,中断,通信等 - STM8L101系列
- 最低功耗模式:0.30 uA
- 动态运行模式:150 uA/MHz
- STM8L151/152系列
- 最低功耗模式:0.35 uA
- 动态运行模式:180 uA/MHz
- STM8L162系列
- 最低功耗模式:0.35 uA
- 动态运行模式:180 uA/MHz
- STM8L051/052系列
- 最低功耗模式:0.35 uA
- 动态运行模式:180 uA/MHz
|
|
|
| | | | | | | | | | | | | | | | | | | | | 本来是上传资料的,但是文件大
谁需要相关的资料可以留下邮箱
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 我们这个小车用到的单片机为STM32F103RBT6,这是基本的资料
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 这是芯片的官网链接http://www.stmcu.com.cn/Product/ ... f1/pn/STM32F103RBT6可以参考一下对于STM32系列的芯片编程时用寄存器和库函数都可以,51的IO的输出输入不需要配置寄存器,stm32的IO使用前得配置相应的寄存器,并且stm32的IO口都可以通过配置触发外部中断,在使用过程当中对IO口的操作最频繁,先说GPIO库
(1) 使用RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE)函数使能GPIO的AHB总线时钟。 (2) 使用GPIO_Init()函数对每个引脚进行四种可能的配置 《1》 输入状态:Floating(浮空), Pull-up(上拉), Pull-down(下拉) 《2》 输出状态:Push-Pull (上拉下拉)(Pull-up(上拉), Pull-down(下拉) or no Pull(不上拉也不下拉)),Open Drain(开漏) (Pull-up(上 拉), Pull-down(下拉) or no Pull(不上拉也不下拉)),在输出模式,速度配置成2MHZ,25MHZ,50MHZ和100MHZ. 《3》 第二功能:上拉下拉和开漏 《4》 模拟:当一个管脚被用作ADC通道或者DAC输出的时候,需要配置成此模式 (3) 外设的第二功能: 《1》 在ADC和DAC模式,使用GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AN把需要的管脚配置成模拟模式 《2》 对于其它的管脚(定时器,串口等): 使用GPIO_PinAFConfig()函数把管脚和需要的第二功能进行连接 使用GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF把需要的管脚配置成第二功能模式 通过成员变量GPIO_PuPd, GPIO_OType and GPIO_Speed选择类型,上拉下拉和输出速度 调用函数GPIO_Init() (4) 在输入模式,使用函数GPIO_ReadInputDataBit()得到配置好管脚的电平 (5) 在输出模式,使用函数GPIO_SetBits()/GPIO_ResetBits()设置配置好IO的高低电平 (6) 在复位过程和刚刚复位后,第二功能是无效的,GPIO被配置成了输入浮空模式(JTAG管脚除外) (7) 当LSE振荡器关闭的时候,LSE振荡器管脚OSC32_IN和OSC32_OUT可以作为通过IO来使用(分别用PC14和PC15表示)。LSE的优先级高于GPIO函数 (8) 当HSE振荡器关闭的时候,HSE振荡器管脚OSC_IN和OSC_OUT可以作为通用IO(PH0,PH1)来使用。HSE的优先级高于GPIO函数。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 这都是介绍的标准库,其实库函数就是把寄存器用结构体封装了吧,由于stm32的寄存器不像51那么简单,非常多的寄存器,要是一一配置很麻烦,用库函数很方便,但是要对相关的寄存器有所了解,
具体函数说明 初始化和配置相关函数 1. void GPIO_DeInit(GPIO_TypeDef* GPIOx) 函数解释:gpio的反初始化函数,该函数的作用是把GPIO相关的寄存器配置成上电复位后的默认状态,在第一次初始化前或者不再使用某一个接口后可以调用该函数。 函数参数说明:GPIOx:gpio的分组,如GPIOA GPIOB GPIOC等的宏定义(这些宏定义在头文件stm32f4xx.h中,由厂家写好,我们直接使用即可)
2. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef*GPIO_InitStruct) 函数解释:gpio的初始化函数,该函数的作用是对io进行初始化。 函数参数说明:(1)GPIOx:gpio的分组,如GPIOA GPIOB GPIOC等的宏定义。 (2)GPIO_InitStruct:gpio的初始化相关结构体。该结构体里面的成员变量决定了我们具体的初始化参数。以下进行说明: l GPIO_Pin:指定具体的IO脚,如GPIO_Pin_0 GPIO_Pin_1这样的宏定义,这些宏由厂家写好,我们直接使用即可。 l GPIO_Mode:指定gpio的模式,有以下四种模式: GPIO_Mode_IN(输入),GPIO_Mode_OUT(输出),GPIO_Mode_AF(第二功能),GPIO_Mode_AN(模拟),可以直接使用这四种宏定义。 l GPIO_Speed:指定IO的最快翻转速度,也就是当使用IO产生频率(如PWM)的最快速度。有以下四种速度的配置: GPIO_Low_Speed (低速),GPIO_Medium_Speed(中等速度),GPIO_Fast_Speed(快速),GPIO_High_Speed(高速),可以直接使用这四种宏定义。 l GPIO_OType:指定选择管脚的输出类型,有以下两种配置: GPIO_OType_PP (推挽方式输出),GPIO_OType_OD(开漏方式输出),可以直接使用这两种宏定义。 Tips: 推挽输出:推挽输出就是单片机引脚可以直接输出高电平电压。低电平时接地,高电平时输出单片机电源电压。这种方式可以不接上拉电阻。但如果输出端可能会接地的话,这个时候输出高电平可能引发单片机运行不稳定,甚至可能烧坏引脚。推挽方式的驱动力更大。 开漏输出:开漏输出就是不输出电压,低电平时接地,高电平时不接地。如果外接上拉电阻,则在输出高电平时电压会拉到上拉电阻的电源电压。这种方式适合在连接的外设电压比单片机电压低的时候。 l GPIO_PuPd。指定选择管脚的上拉和下拉模式。有如下三种配置: GPIO_PuPd_NOPULL(不上拉也不下拉),GPIO_PuPd_UP(上拉),GPIO_PuPd_DOWN(下拉)。Tips:这些都是IO的内部上拉或者下拉模式,也可以接上拉和下拉电阻通过硬件进行外部上拉和外部下拉。
3. void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) 函数解释:gpio结构体的初始化。对GPIO_InitStruct结构体进行默认配置 函数参数说明:GPIO_InitStruct,直接传入该结构体的指针,在该函数内会对结构体进行初始化。
4. void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 函数解释:锁定gpio的寄存器,锁定的寄存器是GPIOx_MODER,GPIOx_OTYPER, GPIOx_OSPEEDR,GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH。在下一次复位前,被锁定的管脚不能被修改。 函数参数说明:GPIOx:gpio的分组(如GPIOA,GPIOB等)。GPIO_Pin:具体的gpio管脚(如GPIO_Pin_0 GPIO_Pin_1这样的宏定义)
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | 上面已经初步了解库函数,对于stm32的学习我们需要看看这几个文档1、ARM Cortex-M3权威指南(中文版) 这是对M3内核的了解 2、STM32F10xxx参考手册 这个非常重要,相当于单片机的硬件手册,包括时钟、电源管理、寄存器等 3、STM32F101xx与STM32F103xx 固件函数库 这个使用库函数编程时的库函数手册 4、stm32参考手册 这个就是一些参考例程 5. stm32芯片手册,就是对引脚功能的介绍等 现在整体看一下stm32F101和103的库函数详解
由于这些文件较大,后续通过百度网盘的形式分享给大家
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 那应该是动态变量,直接在主函数里声明全局变量不就行了?
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 现在主要是一些液晶屏显示数组需要多个c文件调用,ad转换的变量也是
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 在点C文件定义比如U8 buffer[1]={0,1};
在头文件中用extern引用
extern U8 buffer[];
一定要注意头文件里不要定义,在c文件里定义
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 刚开始学习编程都一样,都想弄个小程序下载到开发板上看看实际的功能,就像学习51一样从点亮一个灯,流水灯 、 蜂鸣器等等,都需要一个循序渐进的过程,特别刚开始都是参考例程写的,等过一段时间自己敲代码的时候发现程序很乱,根本就没有自己的编程习惯,需要多练,多写,多做,慢慢的养成自己的一套编程思想,
基于stm32的wifi小车,子函数和子文件较多,但是无非都是函数传递和调用,下面是简单流程图
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对于小车来说,PWM控制用的较多,这种控制的应用非常多,比如调光控制等等,在小车当中,通过占空比来控制速度,在stm32中,定时器较多,STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出四个通道CH1-CH4,改变占空比其实就是改变捕获比较寄存器CCR的值,具体pwm输出怎么配置
TIMER输出PWM实现步骤
1. 设置RCC时钟;有关RCC时钟
2. 设置GPIO时钟;有关PWM通道的引脚配置
3. 设置TIMx定时器的相关寄存器;
4. 设置TIMx定时器的PWM相关寄存器。
对于PWM的输出模式,两种模式,输出极性相反,详细的介绍参考《stm32参考手册》
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对于直流电机的驱动用H桥电路较多,如下图所示,
电机的正反转靠对角线三极管的导通来控制,前面三极管驱动,图腾柱式的驱动电流较大,根据三极管导通的条件,前面两个信号电平相反时电机才会转,我们在这用的集成块L298N,原理图如下
在小车上用了四个直流电机,左边两个电机并联, 右边两个电机并联,四驱,驱动十足,
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 看看具体是怎么控制电机调速的,通过控制使能端使L298N处于工作和不工作,VSS-9引脚为芯片供电 VS-4引脚为电机供电 ENA-6引脚为通道1使能端,利用定时器的pwm输出作用于ENA,根据脉冲占空比不同就可以得到不同的输出电压,从而达到调速目的。比如在VS引脚加10V的电机供电电压,ENA端脉冲占空比为100%,那么OUT1和OUT2之间将输出10V电压,占空比为50%,那么输出为5V电压,占空比为10%,则为1V 我买的电机供电电压为5v到12v都可以,电压高的话也可以,长时间工作的话会对电机损坏,TIMER2.3.4.5中任一个选择PWM输出
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | stm32学习的资料都可以下载看看,最后的程序这块调试完毕会开源的,有时间会更新到HAL库共同学习
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 中间小插曲,继续更新PWM输出的程序
第一步
RCC的初始化
现在用这个系统时钟初始化函数SystemInit();就可以了
第二步
GPIO的设置
- void TIM5_GPIO_Config(void) 在这里用定时器5举个例子,CH1和CH2两个通道来控制L298的使能脚来调速
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
复制代码
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 第三步定时器的设置
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_TimeBaseStructure.TIM_Period = ARR;
- TIM_TimeBaseStructure.TIM_Prescaler = PSC;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
复制代码第四步
PWM设置
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 通道1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CRR;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC1Init(TIM5, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CRR;
- TIM_OC2Init(TIM5, &TIM_OCInitStructure);
- TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable);
- TIM_Cmd(TIM5, ENABLE);
复制代码 设置自动装载值计算pwm频率=72M/((ARR+1)*(PSC+1))
占空比=CRR/ARR通过改变CRR捕获比较寄存器的值来改变占空比 |
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 正反转的原理就不多说,主要说一下左右转,双电机差速转向,所谓的差速,是指左右两车轮的速度差,假如左边车轮比右边的快,则小车会偏向右。同时,左的的车轮转速比右的慢,那么小车会向左边转动。目前主要有以下两种方式。(1)小车向左转,可是是左轮停止或反转,右轮继续转动,这样可实现左转,这种方式实现小角度的转弯,在角度不大时可采用此种方式。 (2)小车向左转,可以是左轮反转,右轮正转,这样可以实现大角度的左转,甚至可以进行原地打转。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 看了上面电机动作的配置图后,对了小车的转向不是舵机控制的,这个角度都是固定的,开始对IO口的预定义#define DIANJI_A_EN_High GPIO_SetBits(GPIOA,GPIO_Pin_0); 控制两个电机的速度
#define DIANJI_A_EN_Low GPIO_ResetBits(GPIOA,GPIO_Pin_0);
#define DIANJI_B_EN_High GPIO_SetBits(GPIOA,GPIO_Pin_1);
#define DIANJI_B_EN_Low GPIO_ResetBits(GPIOA,GPIO_Pin_1);
#define DIANJI_A_CON1_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_6); 依次对应电机的IN1-IN4
#define DIANJI_A_CON1_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_6);
#define DIANJI_A_CON2_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_7);
#define DIANJI_A_CON2_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_7);
#define DIANJI_B_CON1_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_8);
#define DIANJI_B_CON1_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_8);
#define DIANJI_B_CON2_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_9);
#define DIANJI_B_CON2_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_9);
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对电机IO口的配置 都设置成推挽输出模式就可以了
void DIANJI_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 |GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 |GPIO_Pin_9);
}
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 向上计数模式下,使能定时器后TIMx_CNT会从0开始往上数,在模式1中,如果CNT小于设置的值(TIMx_CCR1的值)那么此时CC1通道输出的是高电平,大于设置的值时是低电平,CNT继续往上数,到重装寄存器的值时会更新为0,继续一个周期
现在应该明白了吧
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 是不是每次记一次数都和crr比较吗,crr越大占空比就越大
|
|
|
|
| | | | | 楼主您好 请问怎么在STM8MCU里面同时可以用库函数和寄存器两种方式编程,要怎么设置?谢谢
|
|
|
|
| | | | | | | | | 寄存器的话就这两个头文件,其他根据功能需要添加相应的头文件
|
|
|
|
| | | | | | | | | | | | | 平时上班也没时间,周日有时间继续调试程序,结果出现编译错误..\Output\Main_Uart.axf: Warning: L6304W: Duplicate input file ..\output\system_stm32f10x.o ignored.
原因是 system_stm32f10x.c文件添加了多次,
|
|
|
| | | | | | | | | | | | | | | 明白了,我是在我们以前做的分选机基础上做的程序,在这个USER文件里添加了 system_stm32f10x.c,但是没注意在内核文件CMSIS也有这个system_stm32f10x.c文件
删除一个后编译
整个工程文件调试完毕
|
|
|
| | | | | | | | | | | | | | | | | 楼主这程序终于完了,怎么下载到板子上呢,用啥工具啊
|
|
|
| | | | | | | | | | | | | | | | | | | 这是ST-link的下载工具
用USB转串口的也可以
|
|
|
| | | | | | | | | | | | | 寄存器操作方便效率很高,但是像STM32那样,寄存器太多了,用库函数的较多
|
|
|
|
| | | | | | | | | 8位的单片机多的是,寄存器和库函数都可以操作的额,比如STC15用库函数的也不少 |
|
|
| | | | | | | | | | | 前面介绍直流电机的驱动,现在看一下舵机的工作原理和怎么控制
舵机的工作原理。舵机常用的控制信号是一个周期为20毫秒左右,宽度为1毫秒到2毫秒的脉冲信号。当舵机收到该信号后,会马上激发出一个与之相同的,宽度为1.5毫秒的负向标准的中位脉冲。之后二个脉冲在一个加法器中进行相加得到了所谓的差值脉冲。输入信号脉冲如果宽于负向的标准脉冲,得到的就是正的差值脉冲。如果输入脉冲比标准脉冲窄,相加后得到的肯定是负的脉冲。此差值脉冲放大后就是驱动舵机正反转动的动力信号。舵机电机的转动,通过齿轮组减速后,同时驱动转盘和标准脉冲宽度调节电位器转动。直到标准脉冲与输入脉冲宽度完全相同时,差值脉冲消失时才会停止转动!,这就是舵机的工作原理。
转动角度一般都是0到180,三根线,电源和地,一根控制线,
|
|
|
| | | | | | | | | | | | | 对**云台控制需要两个舵机,需要两个GPIO口来控制,注意脉宽的周期20ms用模拟pwm和定时器输出pwm都行,上面已经介绍了用硬件pwm的方式,这次介绍模拟pwm的原理
PWM就是一个占空比可调的方波信号,用IO口来模拟,设置一个定时器,比如循环从1数到1000,到1000的时间为PWM的周期,设置占空比N,IO口初始为高电平,当定时器计数>N的时候,IO口变为低电平,当定时器计数到1000的时候,IO口变为高电平,这样一直循环,只需调整占空比x就可以了。
|
|
|
| | | | | | | | | | | | | | | 举个例子利用定时器中断模拟pwm,首先对定时器计数更新周期配置
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 399; 这样计算定时器溢出周期400/72us
TIM_TimeBaseStructure.TIM_Prescaler =0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
//ÖжÏÓÅÏȼ¶NVICÉèÖÃ
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE);
void TIM3_IRQHandler(void) //中断服务函数
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
pwmcount++;这是溢出次数
if(pwmcount == 3600)//20ms pwm的周期
{
pwmcount = 0;
}
if(pwmcount ==M) M的值就是占空比控制舵机的转向
}
|
|
|
| | | | | | | | | | | | | | | | | 所有的控制都是从串口发给单片机,单片机解析一下让io口动作超声波避障这块简单介绍一下,超声波避障小车,就是利用超声波来检测小车的前方是否有障碍物,超声波有俩个圆筒状东西,上面发的图片可以看到 ,其中一个是发射声波一个是接收声波,超声波在遇到障碍区时就会反射回来,我们通过计算从声波发射到接收的时间就可以算出其本身到障碍物的距离,计算方式为:速度(340m/s)*时间/2=距离 ,声音的在空气中传播的速度为340m/s,除以2是因为测试的时间是往返的时间,这样我们就得到了距离。
单片机的计算方法是采用定时器计数的方式:当给超声波Trig(发射端)一个高电平即开始计数,等到Echo(接收端)收到高电平信号时停止计数,得到计数值后算出时间带入上面的公式即可。
|
|
|
| | | | | | | | | | | | | | | | | | | 程序这块就是必须先给模块触发脚高电平信号,短暂延时拉低信号,等到接收端输出信号是低电平停止计数,需要对引脚配置成输入悬浮模式,
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC,GPIO_Pin_8);
GPIO_ResetBits(GPIOC,GPIO_Pin_9);
|
|
|
| | | | | | | | | | | | | | | | | | | | | 我们要采用定时中断的方法来计算超声波发射和接受的时间,下面定时设置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_DeInit(TIM4);
TIM_TimeBaseStructure.TIM_Period=6000;
TIM_TimeBaseStructure.TIM_Prescaler=0;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM4,200,TIM_PSCReloadMode_Immediate);
TIM_ARRPreloadConfig(TIM4, DISABLE);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM4, DISABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 对于串口接受这块的通信协议就是普通的8n1方式,没有校验具体协议 帧头 类型位 命令位 数据位 帧尾
我们只需判断中间几位去执行相应的操作就是了
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 其实刚开始对wifi传输图像很感兴趣,因为没有明白其中的原理,当你明白以后就不觉得好奇了,首先我们在生活中看到的视频都是又静止的画面组成的,比如每秒传输30帧图像,由于人眼的视觉暂留效应,所以看起来就是动态的画面,到底wifi模块发送啥东西给手机APP显示呢,通过查阅资料,才了解到发送的是JPG的数据流,通过SOCKET的方式完成传输的
看看SOCKET是怎么传输的, http://www.cnblogs.com/Sniper-qu ... /06/22/2086636.html,对网络通信了解的话,数据是通过IP和端口来传送的,肯定要建立客户端和服务器,路由器就是服务器,客户端发送JPG数据流,视频就是这样传输的
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 把串口通讯这块的程序简单介绍一下
stm32F10系列当中,PA9 PA10串口引脚用的太多了,设置如下用串口中断的方式
GPIO_InitTypeDef GPIO_InitStructure;,配置一下串口时钟,中断等
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 简单总结一下串口通讯的方式,查询和接受
查询,查询方式就是CPU间断地查询串口的接受发送标志,决定是否进行后续处理,在查询的间隙里做其他工作。如果串口波特率较高,CPU在间隙里的任务比较重,工作时间比较长,就会出现丢失接收数据现象,因为串口接收缓冲器只有一个字节,不及时读取就会被覆盖。
中断,假设程序在不停的运行中,当串口有字符时,程序会被中断,然后执行专门的串口执行程序。执行完后,又恢复原来程序。
中断方式下单片机可以放心干其他的活,一旦串口有一个字节有效接收数据或者发送一个字节完毕,串口会立即通知CPU进行后续处理。特点是可靠、及时、占用CPU资源少。
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | 软件模拟是定时中断实现的,硬件PWM是一个外设,设置好就在一边跑了,让内核有更多时间去做其他事情,软件PWM需要一直在计算判断,如果遇到中断还会延时,实时性没硬件的高。
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 是啊,定时器一直在工作,中断溢出,硬件PWM比这个好
|
|
|
|
| | | | | | | | | | | | | asm("halt")这是进入停机模式,功耗很低,比如你用按键的话
if(te==0){ asm("halt");}
void KEY2Init() //PB0做外部中断
{
PB_DDR_bit.DDR0 = 0; //
PB_CR1_bit.C10 = 1; //
PB_CR2_bit.C20 = 1; //1
EXTI_CR1_bit.P0IS = 2;//2 /
EXTI_CONF_bit.PBLIS = 0;
}
#pragma vector = EXTI0_vector //2 //外部中断线2_中断向量号
__interrupt void GPIOB_Line0_IRQHandler(void) //2
{
if(EXTI_SR1_bit.P0F == 1) //2
{
delay(500);
if(EXTI_SR1_bit.P0F == 1)
{
EXTI_SR1_bit.P0F = 1;//清除中断标志
//delay(1500);
//delay(1500);
//PD_ODR_bit.ODR3 = 1; //关背光
if(te == 0) te = 1;
else te = 0;
}
}
}通过外部中断来唤醒
|
|
|
|
| | | | | | | | | | | | | | | 能达到uA级就可以了,在进入停机模式之前把外设都关闭
|
|
|
| | | | | | | | | | | | | | | | | 主要是电池需要链接一些电阻和电容,最好是能把电池直接断了
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 非常感谢啊,这个是通过按键的时间长短来进行开关机吧
|
|
|
|
| | | | | | | | | | | 这是小车初步完成的照片,可以看一下,基本功能实现了,手机APP连接小车的wifi信号,摄 像 头可以通过wifi模块传输给APP显示,小车的前后左右都可以控制,摄 像 头采用云台控制,前后左右都可以
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | 我以前测试12.6v的锂电池,三串三并12650的2600ma,30W放电的话能放2.5h,电量这块可以加上
|
|
|
|
|
|
| | | | | | | | | | | | | | | 后续可能会有小车遇到障碍时,小车会说话“我是21世纪电源网。。。”内容帮忙想想
|
|
|
|
| | | | | | | | | | | | | | | | | | | 人工智能就是图标中梦想DREAM,加个语音模块试试
|
|
|
|
|
|
|
| | | | | | | | | 看看小车到底咋样,把程序下载到mcu里边看看效果,这次用串口下载软件mcuisp
可以直接下载
MCUISP.rar
(731.94 KB, 下载次数: 14)
|
|
|
|
| | | | | | | | | | | | | 将硬件连接好,RXD,TXD不要连错,开始打开mcuisp下载程序,选择好COM口和波特率,DTR高电平复位,RTS高电平进bootloader就可以嗲开始编程了,
|
|
|
|
| | | | | | | | | | | | | | | | | 给小车供电用锂电池,小米**用小米充电宝,
我们打开手机APP连接小车的wifi
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | 程序中还又有关IIC通讯,其实IIC通讯在工作中用的较多,接下来我们共同巩固一下这方面的知识,
I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | 在iic通讯中,有两个地址需要注意一下不要混在一起了,
一个器件地址 device address比如24c02(AT24C02的芯片地址为1010,其地址控制字格式为:1010 A2 A1 A0 R/W 。其中A2,A1,A0为可编程地址选择位。A2 A1 A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该器件的地址码。R/W为芯片读写控制位,该位为0,表示对芯片写操作,为1,表示对芯片读操作。)
一个是寻址地址word address是用来找存储空间的,其寻址范围为0x00-0xff,共256个寻址单元都是针对24c02来说的,一个地址可以存储一个字节(8位数据)
IIC协议的详细运用.docx
(14.6 KB, 下载次数: 11)
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 具体程序中是怎么设置的,用模拟IIC的方式看看IIC的驱动怎么写
就主要就是IIC的初始化,怎么发送应答信号和停止信号,啥时候发送,啥时候停止,上面原理中已经介绍了
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 接着就是IIC的读写程序这块,对一定长度的数据怎么写入和读取
- //³õʼ»¯IIC½Ó¿Ú
- void AT24CXX_Init(void)
- {
- IIC_Init();
- }
- //ÔÚAT24CXXÖ¸¶¨µØÖ·¶Á³öÒ»¸öÊý¾Ý
- //ReadAddr:¿ªÊ¼¶ÁÊýµÄµØÖ·
- //·µ»ØÖµ :¶Áµ½µÄÊý¾Ý
- u8 AT24CXX_ReadOneByte(u16 ReadAddr)
- {
- u8 temp=0;
- IIC_Start();
- if(EE_TYPE>AT24C16)
- {
- IIC_Send_Byte(0XA0); //·¢ËÍдÃüÁî
- IIC_Wait_Ack();
- IIC_Send_Byte(ReadAddr>>8);//·¢Ë͸ߵØÖ·
- IIC_Wait_Ack();
- }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //·¢ËÍÆ÷¼þµØÖ·0XA0,дÊý¾Ý
- IIC_Wait_Ack();
- IIC_Send_Byte(ReadAddr%256); //·¢Ë͵͵ØÖ·
- IIC_Wait_Ack();
- IIC_Start();
- IIC_Send_Byte(0XA1); //½øÈë½ÓÊÕģʽ
- IIC_Wait_Ack();
- temp=IIC_Read_Byte(0);
- IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ
- return temp;
- }
- //ÔÚAT24CXXÖ¸¶¨µØַдÈëÒ»¸öÊý¾Ý
- //WriteAddr :дÈëÊý¾ÝµÄÄ¿µÄµØÖ·
- //DataToWrite:ҪдÈëµÄÊý¾Ý
- void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
- {
- IIC_Start();
- if(EE_TYPE>AT24C16)
- {
- IIC_Send_Byte(0XA0); //·¢ËÍдÃüÁî
- IIC_Wait_Ack();
- IIC_Send_Byte(WriteAddr>>8);//·¢Ë͸ߵØÖ·
- }else
- {
- IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //·¢ËÍÆ÷¼þµØÖ·0XA0,дÊý¾Ý
- }
- IIC_Wait_Ack();
- IIC_Send_Byte(WriteAddr%256); //·¢Ë͵͵ØÖ·
- IIC_Wait_Ack();
- IIC_Send_Byte(DataToWrite); //·¢ËÍ×Ö½Ú
- IIC_Wait_Ack();
- IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ
- delay_ms(10);
- }
- //ÔÚAT24CXXÀïÃæµÄÖ¸¶¨µØÖ·¿ªÊ¼Ð´È볤¶ÈΪLenµÄÊý¾Ý
- //¸Ãº¯ÊýÓÃÓÚдÈë16bit»òÕß32bitµÄÊý¾Ý.
- //WriteAddr :¿ªÊ¼Ð´ÈëµÄµØÖ·
- //DataToWrite:Êý¾ÝÊý×éÊ×µØÖ·
- //Len :ҪдÈëÊý¾ÝµÄ³¤¶È2,4
- void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
- {
- u8 t;
- for(t=0;t<Len;t++)
- {
- AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
- }
- }
- //ÔÚAT24CXXÀïÃæµÄÖ¸¶¨µØÖ·¿ªÊ¼¶Á³ö³¤¶ÈΪLenµÄÊý¾Ý
- //¸Ãº¯ÊýÓÃÓÚ¶Á³ö16bit»òÕß32bitµÄÊý¾Ý.
- //ReadAddr :¿ªÊ¼¶Á³öµÄµØÖ·
- //·µ»ØÖµ :Êý¾Ý
- //Len :Òª¶Á³öÊý¾ÝµÄ³¤¶È2,4
- u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
- {
- u8 t;
- u32 temp=0;
- for(t=0;t<Len;t++)
- {
- temp<<=8;
- temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
- }
- return temp;
- }
- //¼ì²éAT24CXXÊÇ·ñÕý³£
- //ÕâÀïÓÃÁË24XXµÄ×îºóÒ»¸öµØÖ·(255)À´´æ´¢±êÖ¾×Ö.
- //Èç¹ûÓÃÆäËû24CϵÁÐ,Õâ¸öµØÖ·ÒªÐÞ¸Ä
- //·µ»Ø1:¼ì²âʧ°Ü
- //·µ»Ø0:¼ì²â³É¹¦
- u8 AT24CXX_Check(void)
- {
- u8 temp;
- temp=AT24CXX_ReadOneByte(255);//±ÜÃâÿ´Î¿ª»ú¶¼Ð´AT24CXX
- if(temp==0X55)return 0;
- else//ÅųýµÚÒ»´Î³õʼ»¯µÄÇé¿ö
- {
- AT24CXX_WriteOneByte(255,0X55);
- temp=AT24CXX_ReadOneByte(255);
- if(temp==0X55)return 0;
- }
- return 1;
- }
- //ÔÚAT24CXXÀïÃæµÄÖ¸¶¨µØÖ·¿ªÊ¼¶Á³öÖ¸¶¨¸öÊýµÄÊý¾Ý
- //ReadAddr :¿ªÊ¼¶Á³öµÄµØÖ· ¶Ô24c02Ϊ0~255
- //pBuffer :Êý¾ÝÊý×éÊ×µØÖ·
- //NumToRead:Òª¶Á³öÊý¾ÝµÄ¸öÊý
- void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
- {
- while(NumToRead)
- {
- *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
- NumToRead--;
- }
- }
- //ÔÚAT24CXXÀïÃæµÄÖ¸¶¨µØÖ·¿ªÊ¼Ð´ÈëÖ¸¶¨¸öÊýµÄÊý¾Ý
- //WriteAddr :¿ªÊ¼Ð´ÈëµÄµØÖ· ¶Ô24c02Ϊ0~255
- //pBuffer :Êý¾ÝÊý×éÊ×µØÖ·
- //NumToWrite:ҪдÈëÊý¾ÝµÄ¸öÊý
- void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
- {
- while(NumToWrite--)
- {
- AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
- WriteAddr++;
- pBuffer++;
- }
- }复制过来汉字不见了
IIC.rar
(3.5 KB, 下载次数: 11)
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 在小车中,我们主要是用来储存电机的速度和云台的角度,比如舵机的初始化
void Init_Steer()
{
u8 i,l,r;
I2C_EEPROM_Init();
I2C_EEPROM_BufferRead(Angle,0x00,8);//´Óeeprom¶ÁÈ¡½Ç¶ÈÖµ
if((Angle[0]==0xff)||(Angle[1]==0xff)||(Angle[2]==0xff)||(Angle[3]==0xff)||(Angle[4]==0xff)||(Angle[5]==0xff)||(Angle[6]==0xff)||(Angle[7]==0xff))//Èç¹û´Óδ±£´æ¹ý½Ç¶È
{
for(i=0;i<8;i++)
{
Angle=0x3C;//¸³³õÖµ
}
I2C_EEPROM_BufferWrite(Angle,0x00,8);//±£´æ
}
adjust=I2C_EEPROM_ReadByte(0x10);//´æ´¢µç»úУ׼±êÖ¾
if(adjust==0xff)adjust=1;//´Óδ±£´æ¹ýÔò¸³1
l=I2C_EEPROM_ReadByte(0x09);//´Óeeprom¶ÁÈ¡×ó²àµµÎ»ÊýÖµ
r=I2C_EEPROM_ReadByte(0x0a);//´Óeeprom¶ÁÈ¡ÓҲ൵λÊýÖµ
if((l>100)||(r>100))//ÅжϵµÎ»ÊýÖµÊÇ·ñºÏÀí
{
l=100;
r=100;
}
speed_left=l*8+200;//µµÎ»Öµ»»Ëã³ÉËÙ¶ÈÖµ
speed_right=r*8+200;//µµÎ»Öµ»»Ëã³ÉËÙ¶ÈÖµ
}
初始化肯定恢复原位的角度,
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 忘了分享iic通讯的四种模式,
主发、主收、从发、从收
我们平时用的大部分都是MCU为主,eeprom为从,比如主发可以从start开始主动发,但是从发一定是先接收到地址之后再被动发,所以模式是分开的。
还有就是读和写是站在主机的立场定义的,读是主机接受从机数据,写是主机发送数据给从机注意:读数据的时候也要先进行写操作,目的是写入器件地址以寻找合适的器件,当器件与地址匹配时,器件会发出一个应答信号,这样就可以让单片机确定该读哪个器件,这样就可以开始读取数据了.
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 区别可大了,iic是一条数据线来收发,不能同时进行的,
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 期待新的功能,对了,您程序写eeprom是隔一段时间写一次?
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 要是电机速度的话,调一次速度需要写入eeprom一次,下次上电读取eeprom从而记忆速度,这个频率不会太频繁,要是在其他产品中,写入频率较高的话可以隔一段时间写入一次
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 可以采用以上的方式,或者选用擦写次数大的eeprom
|
|
|
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | 为了让程序移植方便,现在都用hAl库,况且STMF7系列全部都是HAL库,试着学习一下开始把程序更新到HAL库,先用CubeMX的图形化界面配置好你需要的各个外设,引脚,时钟等信息,然后生成代码,在规定的地方输入自己的代码就可以了
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 这教程很到位,现在都更新hal库了,的确这也是一种趋势了
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 串口用的非常多,简单总结一下,在串行通信中,一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束。在进行传输之前,双方一定要使用同一个波特率设置。波特率就是每秒钟传输的数据位数。串口的方式分为HAL 库轮询,中断,DMA 三种编程模型,记得前面说过 通信方式分为同步和异步,我们通常使用的是异步通信方式.异步通信规定传输的数据格式由起始位(start bit)、数据位(data bit)、奇偶校验位(parity bit)和停止位(stop bit)组成。
记得以前学51单片机时只有轮询和中断两种方式,不多说了,第三种DMA方式就是直接存储器访问,其实就是可以在无需任何 CPU 操作的情况下通过 DMA 快速传输数据,这样节省的 CPU 资源可供其它操作使用,说白了DMA就是一个搬运工,将数据从一个地方搬到另一个地方而不需要CPU处理。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 看看用图形化界面是怎么设置的
在DMA设置栏添加UASART发送TX的DMA。通道自动选择的,方向从存储器到外设。优先级为低。Mode为Normal,Data Width选择Byte。
|
|
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 肯定有HAL库文件,没有库文件,你写的程序和谁对接啊,其实就是个接口文件
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 前面的基本功能都会了,我们通过STM32的CUBE生成robot的配置代码
有关定时器.GPIO.串口的初始化已经好了,下面需要把程序移植到while(1)LOOP中
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 其实和STD库一样,都需要再不厌其烦的添加文件、添加编译路径(你就可以把之前移植时修改好的文件复制过来,大部分内容不用再次修改)主要是一些头文件都需要改,名字都不一样,Hal库使用串口的时候,串口中断实际上的开与否是由HAL函数接管的。看源码可以看到,在HAL_USART_TransmitReceive_IT和HAL_USART_Receive_IT函数中有一处是打开中断的操作。当调用上面这两个函数的时候,HAL会打开发送/接收中断,当操作完成后,会把中断关掉,这时就接收不到消息了。
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我们在移植程序前简单回顾一下定时器的使用,定时器在程序中太广泛了,看看几种延时的方法
1.循环延时法
在51单片机中经常用
void delay(u8 MS)
{
for循环
}
2.滴答定时器延时
这个是内核里面的24位的倒计时Systick定时器,用着非常方便
3.定时中断法
就是用 定时器计数溢出中断,具体原理前面已经讲过了
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 这个效率网上都说寄存器>标准库>HAL库,实际应用当中感觉不出来
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 楼主还是不要用hal库了,好多坑等着你,可以把标准库的源码分享一下
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 源码的新功能正在完善,肯定会分享的,HAL库也在逐步学习
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我们在这里用了三个中断,两个定时器中断,一个串口中断
首先选择中断优先级分组,
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级
然后选择抢占优先级和响应优先级
我们选择分组1,中断嵌套这块,由于串口中断最频繁,设置优先级最高,次之就是舵机了,最后就是超声波避障
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我也是学习,用标准库较多,中断较多的话要上操作系统吗
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 一般都是μC/OS-II的系统,实时性非常好,仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能,但是移植的话需要看看相关的额教程,在这大概介绍一下吧
μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。
1) 核心部分(OSCore.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。
2) 任务处理部分(OSTask.c)
任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。
3) 时钟部分(OSTime.c)
μC/OS-II中的最小时钟单位是timetick(时钟节拍)。任务延时等操作是在这里完成的。
4) 任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。
5) 与CPU的接口部分
是指μC/OS-II针对所使用的CPU的移植部分。由于μC/OS-II是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 前面谁提到过状态机是啥,在这里也简单介绍一下,通俗的说就是在一种状态下再去判断并保持判断的状态,
比如switch(cur_state) //在当前状态中判断事件
{ case s0: //在s0状态
if(e0_event) //如果发生e0事件,那么就执行a0动作,并保持状态不变;
{ //执行a0动作; //nxt_state = s0; //因为状态号是自身,所以可以删除此句,以提高运行速度。
}
else if(e1_event) //如果发生e1事件,那么就执行a1动作,并将状态转移到s1态; { //执行a1动作; nxt_state = s1;
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 在程序中主要用到简单的用法,就是小车的几种模式切换,当小车切换到一种模式时,小车一直在跑,需要将小车停下来,再切换到另一种模式,这里用变量来判断
if(Pre_Cruising_Flag != Cruising_Flag)
{
if(Pre_Cruising_Flag != 0)
{
DIANJI_GO_STOP; 电机停止
}
Pre_Cruising_Flag = Cruising_Flag;
}
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 51单片机都可以上系统啊,何况强大的STM32,但是上linux和windows的肯定是不行的,至少也得ARM9的内核吧
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 本来想加个12864屏来显示电量状态,单片机还有多余的引脚,但是屏也不好固定,
家里的电子设备和配件一大推
对于12864就不多说了,图中小的是晶联讯的12864屏,那个大的是带蓝屏的12864屏,下面上传的程序是12864串口屏的电池电压经过两个分压电阻接IO口并配置AD通道等
12864.rar
(2.93 MB, 下载次数: 5)
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 树莓派的,恩智浦的,ST的开发板也不少啊呵呵,还有迪文的DGUS屏呢,
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对于小车装载多个电机和舵机的话电源供电最好分开,减速电机供电我们选择6v,舵机选择5v,光源选择3.7v到4v供电,mcu选择3.3v供电,我们选择TI的DCDC电源芯片LMR14030,TPS5430来做,上原理图看看
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我们结合充电电路和DCDC电路,我们在充电时又适配器和太阳能板供电,并给负载供电,电池不放电,当前端电压消失后马上切换电池供电,实现无缝切换
看原理图
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 最大功率跟踪是啥意思啊,我看论坛有几个帖子与这个有关
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 论坛上有关这个24650的帖子分享的不错,最大电流10A,发热肯定不小
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 经过焊接调试后功能都正常,电压输出没问题,上焊接图不是太美观啊
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对于电池这块选用都是以18650为主,串串并并,有三串的,两串的,用着很方便,
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 第七期DIY马上就结束了,这几天 会整理整理程序给大家分享,不知大家还记得首页里的图片
图中DREAM(梦想)将在帖子最后揭晓
先看看初学MCU时的电子时钟,加了掉电记忆功能
电子时钟.rar
(58.48 KB, 下载次数: 9)
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 对了上面那个bq24650对充电的电流和电压必须手动调节阻值,TI的BQ24725A更智能化,
bq24725A 是一款高效同步电池充电器,所含元件数较少,适用于空间受限的多化合物电池充电应用。 bq24725A 利用两个电荷泵分别驱动各 N 通道 MOSFET(ACFET、RBFET 和 BATFET),以便自动选择系统电源。 SMBus 控制的输入电流、充电电流和充电电压数模转换器 (DAC) 具有很高的调节精度,该精度可通过系统电源管理微控制器轻松编程。 bq24725A 使用内部输入电流寄存器或外部 ILIM 引脚来调节 PWM 调制,以减小充电电流。 bq24725A 可对 1 节、2 节、3 节或 4 节锂电子电池充电。 - SMBus 主机控制的 NMOS-NMOS 同步降压转换器,开关频率可编程为 615kHz、750kHz 和 885kHz
- N 通道 MOSFET 可自动选择适配器供电或内部电荷泵驱动式电池供电的系统电源
- 增强了过压保护、过流保护、电池、电感器和 MOSFET 短路保护等安全特性
- 可编程的输入电流、充电电压、充电电流限值
- 高达 19.2V 的充电电压精度为 ±0.5%
- 高达 8.128A 的充电电流精度为 ±3%
- 高达 8.064A 的输入电流精度为 ±3%
- 20x 适配器电流或充电电流放大器输出精度为 ±2%
- 可编程的电池损耗阈值,支持电池 LEARN(学习)功能
- 可编程的适配器检测和指示器
- 集成软启动
- 集成环路补偿
- 可对 ILIM 引脚进行实时系统控制以限制充电电流
- 交流适配器工作范围为 4.5V 至 24V
- 5µA 断开状态电池放电电流
- 0.65mA(最大 0.8mA)适配器待机静态电流
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 可以参考这个这个大概的原理图,这是当时在学习这个芯片时网上下载的
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 帖子接近尾声,小车的功能完成,总结一下,小车的上位机APP是用ecllips软件,JAVA语言写的,主要就是对网络的配置,局域网内还可以,把wifi模块配置成AP模式,向外提供无线wifi信号,打开手机可以搜索就可以连上了,通过APP发送指令给wifi模块,然后WiFi模块通过串口给MCU,mcu并解析去执行指令
还有一种需要通过外网即互联网来连接wifi模块(物联网),这只是物联网的wifi控制的一方面
原理 1、设备一旦联网,就是保持在线状态(通过定时发送相应的数据包),类似于QQ。
2、手机一旦登陆APP,就也会同上一样,保持在线。
3、手机发送命令给服务器,服务器会转发给设备。
4、设备有信息上传到服务器,服务器会转发给手机。
首先你的手机和wifi模块都需要连接外网,需要服务器,也就是所谓的云服务器,比如机智云,华为与等等,所有数据都需要经过服务器来转发,手机可以通过4G等方式连入网络, 访问服务器,通过app操作,发送命令到服务器,服务器会通过家里的路由器将你的命令转发到你的wifi模块,根据你所发出的命令控制相对应的外设
在wifi小车中单片机需要处理的上百个指令,需要有序的去判断执行,不能出现冲突,就需要中断的优先级来处理,这样才能井井有序的运行,比如前后左右,左转,右转多少度,云台的0到180度控制,都对应了不同指令,加上循迹和超声波避障,至与大灯和电量显示,流水灯等等效果都不难。
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我只是分享了物联网的wifi控制,还有好多无线通讯,比如蓝牙,4G等等
|
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 在小车中经常看到自动循迹,具体啥原理呢,循迹模块我用的是红外传感器。黑线的检测原理是红外发射管发射光线到路面,红外光遇到白底则被反射,接收管接收到反射光,经施密特触发器整形后输出低电平;当红外光遇到黑线时则被吸收,接收管没有接收到反射光,经施密特触发器整形后输出高电平。
有黑线时低电平,无黑线高电平
寻迹传感器装在小车车前,寻迹探头朝下,并让地上的事先部好的黑线处于俩个探头中间,当小车刚要偏离黑线时总有一方探头就会探测到黑线,根据这个方位的探头感测的信息判断小车偏离的方向,并反方向行驶校准方位,如此循环,即为巡线!
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 巡线可以举个例子
if((GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0)&&(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)==0))
{
没有检测到黑线,前进状态
}
if((GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2) == 0)&&(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)== 1))
{
检测到黑线,左右转状态
}
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 小车上好多都用PID对小车的速度和角度进行控制,特别是平衡小车中PID应用非常多,在咱这个小车中也可以用PID到底啥啥呢,说一下P、I、D三个参数的作用。P=Proportion,比例的意思,I是Integral,积分,D是Differential微分。 打个比方,如果现在的输出是1,目标输出是50,那么P的作用是以最快的速度达到50,把P理解为一个系数即可;而I呢?大家学过高数的,0的积分才能是一个常数,I就是使误差为0而起调和作用;D呢?大家都知道微分是求导数,导数代表切线是吧,切线的方向就是最快到至高点的方向。这样理解,最快获得最优解,那么微分就是加快调节过程的作用了。 PID一般有两种:位置式PID和增量式PID。在小车里一般用增量式,为什么呢?位置式PID的输出与过去的所有状态有关,计算时要对e(每一次的控制误差)进行累加,这个计算量非常大,而明没有必要。而且小车的PID控制器的输出并不是绝对数值,而是一个△,代表增多少,减多少。换句话说,通过增量PID算法,每次输出是PWM要增加多少或者减小多少,而不是PWM的实际值。
其实主要作用就是PID闭环控制,让小车走一条直线而不是走着走着歪了,及时能反馈并矫正
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 最后一贴完结HAL库的例程链接: http://pan.baidu.com/s/1i5uzYV7 密码:ye4v
记得图中的梦想吗DREAM小车搭载太阳能电池板和具备最大功率跟踪功能充电板对锂电池充电,还有GPS、4g模块和APP时刻通讯,小车具备导航功能和4g通讯功能,直奔21世纪电源网,必须有光线传感器,避障功能,小车在路上能避开障碍物,低于10%的电量停止行走,当光线较暗不能充电也停止行走,出现故障具备APP唤醒功能,就是一个真正的机器人了。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 楼主的梦想好大啊,太智能了,问个问题,串口可以进中断,但是不判断指令
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 可以进中断就不是单片机的 问题,是你指令接受的问题
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 我是先判断帧头和帧尾,再去判断中间的指令,应该没问题吧
|
|
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 给你举个例子吧,比如定义一个全局数组buffer[10](这个缓存区有10个字节),一个全局变量x,在中断中,buffer[x]=UART_data,x++,如果buffer[x]==\n && buffer[x-1]==\r,则收到一串命令,flag=1,在main函数中,if(flag==1) switch(buffer)做判断执行,flag=0,大概这个思路。
|
|
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 好的非常感谢,上面举的例子当中那个是换行操作吧,这个就不需要了 |
|
|
|