一、使用的环境
硬件环境:
芯片STM32F103VET6,外部晶振8M,USB电路接口如下图,USB做从设备时,D+引脚要上拉到高电平,这里控制PA8引脚输出低电平即可使能D+为高电平。
软件环境:
代码编辑和编译软件:RT-Thread Studio 1.1.2;RTOS:rt-thread4.0.2;Windows的串口驱动:VCP_V1.4.0_Setup.exe
二、移植修改过程
(一)基础工程的创建
1.项目工程创建
选择RT-Thread Studio的文件->新建->RT-Thread项目
2.选择保存的目录,选择使用的芯片,选择串口及引脚,选择下载工具
3.生成的工程使用内部时钟(在drv_clk.c文件中),往串口输出信息,这个工程可以直接编译下载到芯片中校验工程的正确性。
(二)使用CubeMX生成时钟配置和外设配置
1.在CubeMX中选择使用的STM32F103VE芯片创建工程
2.选择RCC项为外部高速时钟为晶振;选择USB项打开使能,选择USB的IP包;设置时钟频率,主时钟设置为73Mhz,USB时钟设置为48Mhz,cubeMX自动计算分频系数。
3.设置工程选项,生成工程代码。
(三)RT-thread工程修改
1.时钟配置修改
从CubeMX工程的main.c文件中拷贝SystemClock_Config函数的内容覆盖RT-Thred studio工程drv_clk.c文件中的SystemClock_Config函数中的内容,让时钟能使用外部晶振。
2.进行RTOS内核配置,保存。
3.因为STM32F103的时钟要单独打开,在drv_clk.c文件中的SystemClock_Config函数中增加USB的时钟使能,在stm32f1xx_hal_conf.h打开HAL库的USB相关代码编译选项。
4.配置驱动
打开rtconfig.h文件,在USB驱动配置的地方增加USB设备的BSP定义选项和D+上拉电平控制引脚(从drv_gpio.c中按照对应的管脚查到对应的控制编号,如果D+已经接到搞电平可以不用添加这个控制),修改USB_VENDOR_ID 为0x0483,修改USB_PRODUCT_ID为 0x5740(需改这两项才可以使用ST提供的Windows虚拟串口驱动,否则设备被识别为其他设备)
5.main.c函数修改
/ 用于接收消息的信号量 /
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/ 接收数据回调函数 /
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/ 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 /
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void parameter)
{
char ch;
while (1)
{
/ 从串口读取一个字节的数据,没有读取到则等待接收信号量 /
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/ 阻塞等待接收信号量,等到信号量后再次读取数据 /
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/ 读取到的数据通过串口错位输出 */
rt_device_write(serial, 0, &ch, 1);
}
}
int main(void)
{
int count = 1;
int err = 0;
rt_thread_t tid;
char buf[] = “hello rt-thread!
”;
serial = rt_device_find(“vcom”);
if (!serial)
{
rt_kprintf(“find failed!
”);
return RT_ERROR;
}
err = rt_device_init(serial);
if (!serial)
{
rt_kprintf(“find failed!
”);
return RT_ERROR;
}
err = rt_device_open(serial, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
//初始化信号量
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
// 设置接收回调函数
rt_device_set_rx_indicate(serial, uart_input);
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
while (count++)
{
rt_device_write(serial, 0, buf, rt_strlen(buf))
LOG_D("Hello RT-Thread!")
rt_thread_mdelay(1000)
}
return RT_EOK;
}
5.测试收发,串口工具要打开DTR控制
原作者:浪花雷雨