文章目录
1、USB设备介绍2、虚拟串口进行数据收发1、在stm32F1上进行2、在stm32F4上进行
3、大容量设备访问内部flash
1、USB设备介绍
USB,即为通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。USB接口支持设备的即插即用和热插拔功能。USB是在1994年底由英特尔、康柏、IBM、Microsoft等多家公司联合提出的。
标准 USB 共四根线组成,除 VCC/GND 外,另外为 D+,D-;这两根数据线采用的是差分电压的方式进行数据传输的。在 USB 主机上, D-和 D+都是接了 15K 的电阻到低的,所以在没有设备接入的时候, D+、 D-均是低电平。而在 USB 设备中,如果是高速设备,则会在D+上接一个 1.5K 的电阻到 VCC,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 VCC。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。
正点原子精英板上采用的USB如下所示: USB设备框图如下所示: 这里我们还是不讨论USB过多的原理性的东西,重点还是介绍怎么使用USB这个设备,就是他的驱动,一些相关资料我都传到我的gitee上了,需要的可以自行获取。
这里比较推荐看这个视频,USB讲的还是很不错的 https://www.bilibili.com/video/BV1F64y1U7d8?spm_id_from=333.337.header_right.fav_list.click
2、虚拟串口进行数据收发
1、在stm32F1上进行
首先是配置cubemx开启USB功能 下面我们要使用USB的功能需要配置这个中间件,说白了就是对应的库 下面我们来看下这个配置的一些参数,这一部分其实默认即可,不用怎么修改 继续看设备描述 这里我们看下插上电脑的设备,已经可以正常运转了,就是正常监测到我们我们刚才设置的端口了 这个时候我们就可以用虚拟串口收发函数来进行测试了 将程序下载到开发板,可以看到效果如下: 当然我们也可以用对他进行格式化包装,让他可以像prinf一样的工作,封装的代码如下所示:
void usb_printf(const char *format, ...)
{
va_list args;
uint32_t length;
va_start(args, format);
length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);
va_end(args);
CDC_Transmit_FS(UserTxBufferFS, length);
}
这样我们就可以在主函数中进行调用了! ![在这里插入图片描述](https://img-blog.csdnimg.cn/8d5fdbcc5d534ffaa51c4ca92143cb7a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qGD5oiQ6LmKMi4w,size_20,color_FFFFFF,t_70,g_se,x_16)
2、在stm32F4上进行
这里如果也是按照就是原设定的步骤的话不太成功,会出现就是找不到设备的问题,采用的f4的板子上采用USB连接图如下: 这里后面还尝试了好几种方案,反正都是不太成功,如果有正好看到这篇文章的大佬清楚的话欢迎指正!
3、大容量设备
在前面的文章中,已经介绍过相关STM32内部flash的操作,还有读写外部挂在的flash,以及外部挂载的eeprom,以及使用SDIO还有SPI来读写SD卡,这里我们了解了USB,就可以用USB来作为接口,将这些内存设备通过USB接口和电脑等设备进行交互了,实现类似U盘的功能,相关的链接如下,需要的可以去下了解下:
stm32内部Flash读写 sd卡读写移植记录
这里我们再来看下他的这个USB功能描述: 可以看到USB设备支持的功能还是挺多的,这里就主要介绍这个大容量储存这块的设计,通过设计大容量储存的接口,就可以使得我们得以访问内部的flash以及一些外接的sd卡这样的!
访问内部flash
在前面的文章中已经讲过就是如何将STM32编译出的FLSH表达出来,上次用的是keil的方式,这里我继续采用CUBEIDE的方式介绍下吧!
首先还是看下keil的,编译情况如下,那么它所占的的内存为14236+344=14580的大小,这个单位是字节,那么换算成我们熟悉的点来说就是:14580/1024=14.238KB 这里我们可以看下另一个cubeide的工程: 这里有个大佬讲过了这些字段的意思 https://blog.csdn.net/wxh0000mm/article/details/80364701
详细的解释
text代码和常量data初始化的全局变量bss未初始化的变量dec就是前面三个的加和
这里占用的代码大小就是: 转化成我们熟悉的kb来说就是: 这里我用的是103RCT6,总的FLASH大小是: 这里再看下我们的FLASH占用情况,可以说是基本一致了,基于这些情况我们就可以开始来设计这个flash的内存设置了 我们这里内存占用是49kb的样子,因此这里我们就从60KB之后来算(这个只要大于49就都是合理的),具体计算如下所示: 将他转换成我们熟悉的KB值,因此这个就是60KB了 我们在新建的工程里来设置这个大小和起始地址: 之后在这里将我们刚才设置的加入进去 之后就可以添加读函数还有写函数了 这里我附上源码,需要参考的可以借鉴查看
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
if (lun == 0) {
memcpy(buf, (uint8_t*) (FLASH_START_ADDR + blk_addr * FLASH_PAGE_SIZE),
blk_len * FLASH_PAGE_SIZE);
return USBD_OK;
}
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
if (lun == 0) {
uint16_t i;
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef f;
f.TypeErase = FLASH_TYPEERASE_PAGES;
f.PageAddress = FLASH_START_ADDR + blk_addr * FLASH_PAGE_SIZE;
f.NbPages = blk_len;
uint32_t PageError = 0;
HAL_FLASHEx_Erase(&f, &PageError);
for (i = 0; i |