无特殊声明,本站工程开源协议均为MIT license
必须在发行版里包含原许可协议的声明,无论以二进制发布的还是以源代码发布的
本项目为嵌入式课程设计,仅供学习交流使用,如有问题请联系QQ:1764269411
- 百度网盘下载:链接 提取码:DSPI
PartA:使用说明
开发工具:
HAL库,keil MDK
串口上位机vofa+
硬件:
- 主机:STM32F407VET6
- 从机:STM32F103C6T6
- USB转TTL:CH340
技术参数:
- USART 波特率115200
- SPI 全双工带硬件NSS 波特率5.25MBit/s
- ADC 双通道采集 0~3.3V
操作说明:
STM32F407VET6作为主机,采集PA0和PA1两个通道上的ADC信号,通过SPI1与从机STM32F103C6T6的SPI1相连,将ADC数据帧传输到从机。从机SPI1接收数据后,进行数据帧解析出ADC值,再通过USART1发送ADC数据,以Firewater协议形式经CH340传输至上位机VOFA+,上位机可以显示数据及波形。
注意事项:
- 上电后,需复位一次从机。
PartB:系统设计说明
一、系统设计说明
由于仿真时出现无法解决的接收问题,因此本次作业未采用仿真,而是使用实物完成。本系统采用STM32F407VET6、STM32F103C6T6芯片,均配8M外部晶振。
二、系统功能说明
STM32F407VET6作为主机,采集PA0和PA1两个通道上的ADC信号,通过SPI1与从机STM32F103C6T6的SPI1相连,将ADC数据帧传输到从机。从机SPI1接收数据后,进行数据帧解析出ADC值,再通过USART1发送ADC数据,以Firewater协议形式经CH340传输至上位机VOFA+,上位机可以显示数据及波形。
三、软件设计说明
1.工程目录
使用STM32CUBEMX生成MDK5工程。
主机时钟频率168MHz,文件目录树如下:
-Project:MASTER
|-MASTER
|—Application/MDK-ARM
|—Application/User/Core
|—Drivers/STM32F4xx_HAL_Driver
|—Drivers/CMSIS
|—bsp
|——bsp_adc.c/.h
|——bsp_led.c/.h
|——bsp_spi.c/.h
|—app
|——apps.c/.h
从机时钟频率72MHz,文件目录树如下:
-Project:SLAVE
|-SLAVE
|—Application/MDK-ARM
|—Application/User/Core
|—Drivers/STM32F4xx_HAL_Driver
|—Drivers/CMSIS
|—bsp
|——bsp_led.c/.h
|——bsp_spi.c/.h
|——bsp_usart.c/.h
|—app
|——apps.c/.h
2.AD采样
AD采样与数据传输方式为ADC间断扫描方式,软件触发。ADC配置如下图:
使用以下函数获取不同通道的ADC值,在主函数内调用,间隔为10ms,调用后将值存入ADC_BUF数组内,由此获得的未处理的ADC值。
1 | ADC_ChannelConfTypeDef sConfig_chx = |
3.SPI主从机通信
主机SPI配置如下图:
SPI配置为全双工带硬件片选信号NSS的8位帧格式,波特率5.25MBit/s,无CRC校验,时钟空闲电平为低。
从机SPI配置如下图:
从机SPI配置与主机相同,但无需配置时钟信号,需配置硬件NSS片选输入。
直接进行主从通信误码率高,且不方便接收多字节数据。因此定义一个简单的协议帧进行通信。由于待传输ADC数据为16位,因此首先定义半字格式共用体,利用共用体拆解为2个8位进行传输。
1 | typedef union{ |
调用发送函数时,输入的两个ADC数据拆解完后存入发送缓存数组,加上两个帧头0xFF和0xAD后进行发送。
1 |
|
从机接收时,为了保证可以接收到有效数据,因此设定接收缓存区为2倍帧长度,然后从接收缓存区匹配帧头数据进行协议帧解析。匹配帧头后,通过共用体进行拼接,拼接后的数据即为获得的2个ADC数据。
1 |
|
4.串口发送
从机串口USART1配置为默认普通异步串口即可,波特率115200bit/s,无奇偶校验,1位停止位。
要使用printf发送数据,需进行重定向将数据从USART1输出。还需要包含stdio.h,并且要勾选使用MicroLIB,否则程序将卡死。
在bsp_usart.c中,进行重定向:
1 | int fputc(int ch, FILE *f){ |
现在可以使用printf函数,Firewater协议允许发送浮点数,其协议格式如下:
主函数内调用printf发送函数:
1 | printf("ADC ch0,ch1(unit:V): %.2f,%.2f \n",(float)(ADC_receive[0]*3.3f/4096),(float)(ADC_receive[1]*3.3f/4096)); |
由此可以发送接收并换算后的ADC值。
四、调试及运行结果
1.电路连接
主 | 机 | 从 | 机 |
---|---|---|---|
PA4 | SPI1_NSS | PA4 | SPI1_NSS |
PA5 | SPI1_SCK | PA5 | SPI1_SCK |
PA6 | SPI1_MISO | PA6 | SPI1_MISO |
PA7 | SPI1_MOSI | PA7 | SPI1_MOSI |
主机PA0、PA1–>测试电压引脚。
从机USART1–>CH340–>PC 。
实物连接如下图:
2.运行结果
测试组1:测试点0电压2.536V,接PA0。测试点1(GND)电压0V,接PA1。
显示波形:
测试组2:测试点2电压3.3V,接PA0。测试点3,PA1悬空。
显示波形:
五、注意事项
使用ADC进行多通道采样时,需要注意配成ADC间断模式,且每次软件扫描读取时需要先配置好ADC通道,然后开启ADC采集,否则采集结果一直为同一通道的值。SPI数据帧通信可能丢失,因此定义协议帧头进行有协议传输,不易得到错误数据。同时片选信号一定程度上也能减小外界影响,降低误码率。