一、MPU6050 & 光电门–编码器 &摄像头:
➽6050:在mpu6050中我们用陀螺仪传感器测角度,用加速度传感器测加速度。通过IIC对MPU6050寄存器进行读写
VCC:接5V电源
GND:接地
SCL:主IIC时钟线 (我接的PB10)
SDA:主IIC数据线 (我接的PB11)
AD0:地址线,接3V地址为0x68,接地地址为0x69(我接的PA15,高电平,地址为0x68)
检查步骤:先看看能不能读取ID值,MPU6050出现问题的原因有几个:
参考:
https://blog.csdn.net/qq_26039737/article/details/79214887
https://www.shuzhiduo.com/A/KE5Q43AqJL/
➽光电门:
关于io定义:
编码器的两个输入引脚借用了输入捕获的通道1和通道2(CH1和CH2),
CH3和CH4不能接编码器
在PID控制中,反馈是重要的一环,而电机速度的反馈就是通过编码器这个东西反馈。测量方法:
1、需要知道参数(例子):比如A项的上升沿和B项上升沿的时间之差是3.5ms,查阅数据手册可以知道转动一个方格的时候小车走了1cm,即可知道编码器旋转的速度了;E选择了TI1和TI2的话就是实际上是倍频了四次(会读四次),
A波形与B波形一次周期就是会有四次相对的变化,故此时的四倍频是全部计数读取(沿和沿之间的变化);
Input filter 设置为6能很好抑制波动,io口设置为上拉输入;ARR 65535;Counter mode为UP; 程序不会自动打开编码器的接口,需要自己开启:TIM_Encoder_Start;每个编码器需要一个定时器;因为F103的定时器是16位的,所以定时器写入的时候不能大于65535
2、具体知道电机速度的方法(M法测速-路程除以时间):
路程就是脉冲数目,查阅电机的数据手册就可以了解电机旋转一圈会出现几个脉冲;
减速比是34(即电机转轴转1圈,电机本身要转34圈)
电机转一圈的物理脉冲数是11
每一个脉冲所旋转的距离会是: π*d/(脉冲数*4*齿轮加速比例);
例如我使用的电机旋转一周为12个脉冲,乘4再乘齿轮比例4.5等于216;轮径为6cm,也就是直径为18.84约19cm,也就是0.19m,接下来还得取时间:
自己可以用中断去取时间,比如在滴答定时器里面定义i是增到50ms时,根据编码器的读取函数,然后再读取编码器的时间,然后再让他除以50个ms,就可以得到电机此时的运行速度了,返回上位机就行;
但实际上如果要进行PID运算时,并不需要精确的速度,只需要传入脉冲个数,比如50ms,我捕获到他转了100个脉冲,直接把这100个脉冲传给接下来的PID计算的函数;
PID的三个变量调整对应图,右上角是参数赋值:
对于I:累加的I才能回到正确的轨道线1,前面的历史误差让它有回到正确轨道的根据:
VOFA+ 专为PID调试(对接收到数据进行波形绘制):https://www.bilibili.com/video/BV1zT411B7kg/?spm_id_from=333.337.search-card.all.click&vd_source=4e5eec7bb844b69adc695d11b9ce1bb2
➽摄像头:
摄像头处理的数据叫做图像数据,也就是一帧的图像。可以通过lwip中的TCP或者UDP连接到上位机,有分为全帧传送和拆分传送。要先建立连接,才能把图像数据发送到上位机或者云端,通过netconn_accept。
随后再通过netconn_write 来把图像数据写到上位机。然后下面的代码是我们连接到上位机了之后,发出一个关闭请求,然后执行全部代码知道退出这个最里面的循环。
我们的开发板作为服务器上位机,也就是客户端的时候,当客户端也就是网络连接助手,连接服务器的时候,要进入while的时候,需要提前等待客户端连接才能执行里面的代码。
服务器把摄像头处理的数据使用网卡发送至服务器中,并且在服务器实时更新图像。
其中,主要运用了SCCB总线协议:
与IIC协议十分相似,SCCB协议由两条信号线组成-SIO_C(类似IIC的SCL)和SIO_D(类似IIC的SDA)
然后不同的是,应答名字不一样,IIC协议在传输完1字节也就是8位的数据后,还需要有1位的接收方反向发过来的确认位。而SCCB协议一次性要直接由发送方发过来9位,前八位也是数据位,第九位名为 X,表示Do not care,而IIC的应答位叫做ACK。
然后也有区别是SCCB只能单次读,而IIC除了单次读还可以连续读。
最后读操作中,.SCCB读操作中间有stop,而IIC读操作中间可以有stop也可以不需要stop,具体表现如下:
232是连接着串口的,所以需要开发板上面的是连着232而不是Slave
OV7670和OV2640的区别:
ov2640能输出JPEG,前者不能,应用的话我也没用过。又因为例程里面是需要转换成JPEG格式,所以7670跑不了
二、CAN & USB:
CAN:✿芯片型号是TJA1050-是一个CAN总线收发器,能把从单片机内部发来的数据(由内部CAN总线控制器-这是与RS485的区别了,与USART无关)转换成H和L两条线上的电平,PA11和PA12对应的是硬件CAN,
本协议位速率高达1M/s,它可以接收和发送11位标识符的标准帧,也可以接收和发送29位标识符的扩展帧,使用的是双绞线,两端要连着两个120欧的电阻。如果L线和H线接反了,总线就会无法通信。
自拟:
✿与IIC,SPI不同的是,CAN没有时钟线,故是异步通讯。它只有CAN_High和CAN_Low两条信号线,使用差分形式进行通讯(这样两条线的逻辑电平相减的时候,就影响不大,因为变的话是两条线一起变),
虽然有两根线,但是传输的信号只能一种方向,不像SPI有MISO和MOSI这样可以发接同时,所以CAN是异步半双工,它也没有主从设备的概念而已,只能节点满足条件,就能发数据。
✿发送函数:当 CAN 节点需要发送数据时,控制器把要发送的二进制编码通过 CAN_Tx 线发送到收发器,然后由收发器把这个普通的逻辑电平信号转化成差分信号,通过差分线 CAN_High 和 CAN_Low 线输出到 CAN 总线网络
✿接收函数:则是相反的过程,收发器把总线上收到的 CAN_High 及 CAN_Low 的差分信号转化成普通的逻辑电平信号,通过 CAN_Rx 输出到控制器中,这样单片机就能解析出来了。
✿STM32上,CAN要构成通信,除了要有两个接收端子,还要有收发芯片TJA1050。和485相比主要优点是:CAN有ID识别,知道是谁发,然后数据包不用加帧头。485则要帧头帧尾。
如图示意:
☀代码:为了保证通信的成功,所有节点的波特率都要保持一致。
加强理解---CAN:
☀区别:与IIC,SPI具有时钟信号的同步通讯方式不同的是CAN是异步通讯,只有CAN_High和CAN_Low共同构成一组差分信号。(由于差分信号线具有很多优点,所以在USB协议、485协议、以太网协议及CAN协议的物理层中,都使用了差分信号传输。 )
☀逻辑定义:当CAN收发器从CAN_Tx线接收到来自CAN控制器的低电平信号时(逻辑0), 它会使CAN_High输出3.5V,同时CAN_Low输出1.5V,从而输出显性电平表示逻辑0,如下图:
☀CAN的波特率
☀标准数据帧的结构:分为帧起始–仲裁段(总线会根据仲裁段的内容决定哪个数据包能被传输,ID决定着数据帧发送的优先级。
若节点1和2竞争,当他们发送报文的时候,若首先出现隐性电平就会失去总线的占有权转为接收;若为显,则继续发送)–控制段(用于表示本报文中的数据段含有多少个字节 )–CRC段–ACK段( 发送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答 )–帧结束
☀过滤方法有以下两种模式:①标识符列表模式(只有和自己所列表符合的才能接受到) ②掩码模式:掩码,可以把它理解成关键字搜索,只要掩码(关键字)相同,就符合要求,报文就会被保存到接收FIFO。
(前一个寄存器写ID,后一个寄存器写筛选的数字是前一个中的哪几位,两个寄存器为一组掩码)
☀补充:因为CAN总线上的数据是以广播的形式,所以所有连接到CAN上面的节点都会接收到其他节点发出的数据,因而CAN控制器大多具有根据ID过滤报文的作用,它可以控制自己只接受哪些ID的报文。
CAN发送/接收结构体:uint32_t StdId; /*存储报文的标准标识符11位,0-0x7FF. */uint32_t ExtId;/存储报文的扩展标识符29位,0-0x1FFFFFFF./
如果只有一个实验板, 也可以使用CAN的回环模式进行测试,不影响学习的。为此,我们提供了“CAN—双机通讯”及“CAN—回环测试”两个工程。
➽USB协议:
读卡器与虚拟串口实验:读卡器是相当于读SD卡的内存,有多少M.
有主机和从机的相应接口的:
USB协议:应用-USB的读卡器、声卡、虚拟串口是把 stm32作为从机slave,而USB的U盘、鼠标键盘则是把32作为主机host。
介绍-USB是一种主从系统,数据交换只能由主机主动发起。一共由四根线组成: VBUS(电源线)、差分线正、差分线负、电源负。然后全速/高速设备接在D+,低速则在D–,
所以信号线相当于只有一根,所以是半双工。(OTG则是指主从可以随意切换,DFU则是设备固件设计类、CDC是虚拟串口类)协议间内存冲突:USB和CAN共享一个512字节的SRAM,所以不能共同用。
代码移植步骤(这是对于HOST或者SLAVE而言):①查看ST官方的MSC例程
②拷贝工程所需文件(别忘了还有spi工程在NORFLASH上面)
③MDK改成设置
④修改usbd_storage.c
(代码分析:文件系统在外部FLASH的起始地址,因为我们定义SPI FLASH前12M给文件系统用,所以地址从0开始 ; USB状态–用bit0-bit4表示–◆电脑正向SD卡写入/读出数据/ ◆SD卡读/写数据错误标志位 )
⑤修改usbd_conf.h:
⑥修改usbd_msc.h:
为了支持大于4G的内存卡,要把uint32_t scsi_blk_addr改成uint64_t scsi_blk_addr; 并且要将
uint32_t scsi_blk_nbr改成uint32_t scsi_blk_nbr[STORAGE_LUN_NBR],这样才能既支持SD卡又支持SPI _ flash这两个磁盘,所以才要把变量改成数组以支持多个磁盘。这样就有电脑上面显示两个U盘了。
➽IAP:
IAP(In-Application Programming在应用编程)
概念:指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。在应用编程(IAP)是用户的应用代码对片内Flash存储器进行擦除/编程的方法。
设备固件升级(DFU):
也是IAP中的一种,不过这个是ST公司推出来的固件升级方案:
- 概述:利用STM32内置的Bootloader来实现USB DFU(Device Firmware Upgrade)固件升级功能,如何配置STM32芯片以支持USB DFU,并提供相应的代码示例和步骤说明。
USB DFU是一种通过USB接口进行设备固件升级的通用解决方案。它允许开发者通过USB连接来升级设备的固件,而无需使用外部编程器或者其他特殊的硬件设备。
- 工作原理:USB DFU通过在设备内部Flash中提供一个Bootloader程序来实现固件升级。当设备进入DFU模式时,它将暂停运行当前固件,然后通过USB接口与主机进行通信。
主机通过USB传输固件数据给设备,Bootloader程序接收并将固件数据写入设备的Flash存储器中。完成固件数据的传输和写入后,设备重启,并加载新的固件运行。
通常被开发者用来当作远程升级的手段。烧录到flash里面,然后重启之后会重新烧录进拷贝进来的程序。
启动过程:①初始化MSP,从0x8000 0000 ②初始化PC,从0x8000 0004 ④初始化中断向量表 ⑤调用初始化函数SystemInit()。⑥调用_main的标准C库函数。(PC是程序计数器,用来存放和指示下一条要执行的指令的地址; MSP是memory system protection)
- 加入IAP后的烧录启动过程区别:每一次的上电都会有执行复位中断服务函数的过程,正常是接着执行main里面程序,
可是加了IAP之后,就会执行IAP里面的main函数,然后再执行IAP过程,随后就会跳转到APP的中断向量表,也就是自己的hex文件里面的中断向量表,随后再跳转到自己hex文件里面的main函数;
- 然后正常发生中断的时候,会直接跳到中断向量表根据中断源跳转到相应的终端服务函数,可是加了这个IAP之后发生中断时,
会强制跳转到地址为0x8000 0000的中断向量表,随后根据设置的中断向量偏移表,跳转到APP对应的中断服务函数。(IAP过程就是把bin从外面读进来)
- APP生成步骤:
首先要看这个IAP原本的bootloader应用程序要大概多少大小,在IAP.map下面就要24k左右,
而在正点例程里面已经设置成了红框框里面的0x8010 0000,大概就是10000约等于64kb给DFU程序留了64kb后面的才是自己的发送的APP的hex文件的大小,所以APP一定要在bootloader后面,偏移量是0x200的倍数。
总的来说,FLASH是从0x8000 0000开始,SRAM是从0x2000 0000,而对于空间分配,一共要有三部分需要考究清楚-第一部分是Bootloader程序运行预留4kb,然后存放APP程序预留48kb,APP程序运行预留12KB,下面这个图自己标记过了:
- 移植过程:
①设置APP程序的起始地址和存储空间大小'
②设置中断向量表偏移量(也就是比如APP存放在flash的话,也就是SCB->VTOR=FLASH_BASE|0x10000;而SRAM就是SCB->VTOR=SRAM_BASE|0x1000;)
③设置MDK编译后运行fromelf.ex,从而能生成bin
使用RTE试试:这个应该不属于USB协议里面,所以在RTE里面选择不了,有IAP的文件应该就可以更新了,和stmflash.c的文件:
关键代码(正点):
- 学习过程:.bin文件就是有.axf文件生成的;主函数代码分析(对于IAP里面)
※更新FLASH代码:主要用到flash写入数据的函数---STMFLASH_Write(),为什么判断i==512的时候要把i重新赋值为0
※from yang:参考链接-https://blog.csdn.net/ZZZganfan/article/details/134367775?spm=1001.2014.3001.5501