- CAN1,指令及ID
- 配置SPI时需要注意时钟
- 提前使能PA,PB时钟,故在外设初始化里面没有此项。
- 外设有如USART1等直接进行CR1赋值进行配置,具体请自行查询《STM32中文参考手册》
- kalman是连续的,但DT可以跳变。
- 标定的时候插上电池不要断电,不然数据丢失,目前flash文件并未使用
- GPIO配置三个接口都必须复用到SPI,不过CS信号模式为输出,更改为复用后本程序不可行,但理应也是复用,这个目前还无法理解
- 分频系数应该根据系统时钟选择;PB1域为低速时钟,默认36Mhz,最高为48Mhz,对应SPI2;PB2域为高速时钟,默认72Mhz,最高为84Mhz,对应SPI1;
AD8320的时钟频率为0.024-2.4MHz,具体配置应处于状态我目前还不太了解,后面可以问问lyf;不过我目前都将其根据上面的分频设置为一点几,分频系数分别为32和64 - F1 我和lyf配置是一样的,但她的正常,我的程序在运行一段时间后会卡死在while((SPIx->SR & 1<<1)==0)里面,具体原因还不太清楚,不过目前F1依然还是用的输入模式,之后有时间改为复用看看。F4一切正常。
对于解决F1的问题,此处可以将判断改为检测SET位,虽然F1确实有用,但是这样有可能导致return的丢失,具体原理现在依然不清楚,建议还是按默认的检测RESET位。
- 标定数据时,首先,连接好(电池,DT,板子),之后在场地上拉好标尺。
- 打开串口屏的标定页面,在初始位置摆放好DT,观察到KFdata基本不变化时电机_'单点保存',之后'saved'_指示灯变绿,可重复保存覆盖数据。移动DT,重复。 通过更改param.c里面的bgPos定义初始点,默认两点间距为100mm,每次标定最多可保存30个点数据,即3m。
- 保存完毕后,保持上电,电脑打开串口助手,连接USART1,将数据发送至电脑。
3.1 方法一: 每一点逐点发送,点击_'单点发送',观察到'sent'变绿,通过程序定义isSendOnlyOnce选择是否只允许发送一次。保存文件名格式为2000.txt,每次保存后清除串口助手窗口数据,然后串口屏点击加/减当前位置,重复直至所有数据发送并保存。
3.2 方法二: 点击'数据传输'_,将所有数据全体发送至串口助手,保存窗口数据至文件'alldata.txt'
- kalman.c标定好当前DT参数,并根据实际情况选择赋值给下面的DT35Coe_1及DT35Coe_2
中断/事件 | 抢占优先级 | 响应优先级 | 用途 |
---|---|---|---|
USART2_IRQn | 0 | 1 | 串口屏接收 |
TIM3_IRQn | 1 | 0 | 获取DT数据 |
CAN1_RX0_IRQn | 1 | 1 | 主控 |
USART1_DMA | 6 | 1 | 标定及示波器 |
USART2_DMA | 7 | 1 | 串口屏发送 |
- C里面没有C++的构造函数概念,所以结构体里面的const常亮很难正常初始化,也就是基本不用了。
- Kalman_DataTypeDef定义的没有必要,后面再写就把它优化了
- 问题描述: 串口1发送出来的一直有问题,DR寄存器和串口助手上显示的不一样。 经过查询是波特率设置错了,之前USART2->BRR=0x016C,然后USART1也直接设置成这个。但考虑到USART2使用AHB2低速时钟,USART1使用AHB1高速时钟,此时应USART1->BRR=0x02D9. 计算方式如下:
/*
* input: pclk2: 系统时钟
* bound: 设置的波特率
* AHB1: pclk2=84 MHz, AHB2: 42MHz
*/
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);
mantissa=temp;
fraction=(temp-mantissa)*16;
mantissa<<=4;
mantissa+=fraction;
USARTx-BRR=mantissa;
当然,完全可以拿一个配好的库函数程序直接进Debug看一下BRR寄存器直接一抄就行了。完美!(这里引申的话,CR寄存器也直接直接复制)
2. USART1只需要DMA发送,把其他无关的都删了,比如接收中断,或者发送格式函数
3. 现在串口屏已经没问题了,不过还是原来的单点发送。
目前已经将所有数据保存,可以考虑改一下MATLAB里面的函数就不用处理那么多文件了。一直文件6000个数据直接分,当然这对串口发送提高了要求,原来的就不可以,容易发超。
4. CAN寄存器真太多了,不想学,老老实实用库函数吧。
- 串口配置里面的USART1->BRR = (u32)0x016C;其中强制转换u32不可以去除。
- USART2的DMA也换成寄存器了,直接借用原子的函数。
- USART_ReceiveData return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
- 手柄一发信息串口二就溢出了,发现是tim里面的spi数据处理太多了,将USART2的优先级提高到TIM3前面,已解决,(有点饮鸩止渴?)
- 下午更改SPI模式为只接受模式,一切正常,晚上用着不知怎么出问题了,试了几次还是改回来了。
- DMA接收数据时接收多少位一直没搞懂,放弃了
- 继续更改了下配置方式,将GPIOA,GPIOB的使能整体放在main函数的开头,这样配置的时候就不需要多写这几句。led,beep等只需要一行代码配置一下GPIO就可以了,这样就清晰了很多。
- 库函数配置时,每条语句都对应一项配置,但一个外设需要配置的东西太多,很多东西都没写使用默认的方式。这样之前理解还是有些不清楚。
使用寄存器配置,对每一项进行赋值,之前还是一个bit一个bit的单独通过|=的方式进行置位或复位,没有配置的也以默认的方式。
但现在通过今天的尝试,完全可以通过参考文档精准设置每一位的状态,这样得到的就只是一个u16的值,将其赋给CR1完全可以一条语句配置。 诚然,这样一次性配置既有优点也有缺点。
缺点方面,一次配合之后修改较为麻烦,每次配置都需要查询一遍参考文档,进行单独的模块配置很麻烦,比如突然只想更改一下SPI由16位变为8位。别人看代码的时候也不利于理解。
优点方面,对于上面的缺点,队里的情况基本某一项配置好之后基本就不会怎么改,所以这样一劳永逸也是挺好的。配置出现问题时寄存器也比库函数更易查找问题及修改。通过对寄存器的理解,去年最开始学库函数的时候经常出现代码的顺序不对而出现错误这时候已经很了解了。 然后STM32相较于51的优点之一就是有固件库,我这是反而算倒退了吗? 库函数与寄存器,其中寄存器是底层便于理解,而库函数进行了封装,开发周期短,代码可读性强,易于与人配合。对队伍而言,自然是库函数作为首选。对于个人,其实应该学一点寄存器,我现在也算是刚学,所以这时候都用这个写的,但是理应应用库函数,毕竟便于他人。不过如果单纯去只学库函数,尤其对于机械的没有电气的那么强硬的基础,这时候很容易出现知其然不知其所以然的情况,就和我以前一样。
- 程序SPI配好之后转移到了VSCode上
- 寄存器赛高!
目前使用寄存器进行程序配置,对于自己理解底层确实多有帮助,(虽然这样对于别人没学过的可能不太友好,比如学弟看到这程序应该只能ctrl+c ctrl+v),建议还是了解一下,而且配置也变简洁了。 - 今天遇到了个板子晶振坏了,时钟频率不对,展现出来的就是beep和灯的频率不对。这时候自信点,相信硬件的错误。 附:OSTimeDly(1)为0.1ms。
- 王老师寄以厚望啊,队里的驱动器方面需要创新,需要大量工作。
- 串口1用寄存器写了下,但没成功