# FrameWork **Repository Path**: chen-qiuda/frame-work ## Basic Information - **Project Name**: FrameWork - **Description**: 单片机代码框架,以STM32F103为案例 植入操作系统 - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-08-26 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FrameWork 未完成 Seeger NVIC 0优先级最高 #### 介绍 单片机代码框架,以STM32F103C8T6为案例 以标准库,编写各外设驱动。因为STM32系列单片机 寄存器结构相似,故在做外设驱动时,不考虑其他如国产芯片结构 植入操作系统(Target 里可选择修改工程目标,切回裸机模式,不包含及编译操作系统文件) #### 代码规定 1. 硬件层只做硬件事,重复启动相同外设,复制配置驱动参数。 用户层只做用户事,如中断服务函数内容 2. 命名规定:硬件驱动层参数结构体为TypeDef。所有结构体成员命名前缀为ty,方便阅读 3. 所有从驱动层向应用层开放的操作接口,前缀为bsp。C语言不允许先实例化结构体里的函数指针,再创建对象。注册回调函数,在不破坏代码结构的情况下,传递形参数调用用户代码 4. 所有外设的config init函数只完成参数配置和初始化 最终外设enable由bsp函数内完成 5. 哪怕在主循环中和在中断 DMA中 严格意义上都禁止同时读或写同一个缓存,哪怕是在中断中memcpy出去。如果在单一原子变量操作并不会发生(单汇编指令不会发生,单纯读或单纯写),操作32bit变量。尤其是高危场景,明确禁止发生缓存数据一半旧数据一半新数据的情况。 哪怕是双缓冲机制,也无法解决生产>消费的模型,只能提高最大1倍的效率。除非使用多缓冲,解决高并发问题。双缓冲通常会丢弃最新一帧,只保留最新的有效帧 #### 软硬件架构 APB2 72M = ADC123,Uart1,SPI1,TIM1 8 ,EXIT,GPIOx APB1 36M = I2C12,TIM, SPI23, Uart2345 AHB 72M = DMA12 中小容量 F103 没有 DMA2,TIM8、ADC3 不存在; 1. HardFault_Handler ,startup 被修改过,用作栈回溯 2. 驱动层采用 属性+方法的结构, 外设属性会浪费一点内存, 方法为直接调用函数,节省给方法函数指针的赋值操作 3. 外设属性中, 外设时钟线 APB1 APB2 基本不会改变,暂不考虑封装 4. MCU做从机,使用双缓冲结构强制一请求一应答模式,避免发生如MCU从机TX应答断联问题,导致单个指令重复执行。或者加入包号 5. MCU做主机,使用生产者消费者模型,生产者写入环形缓冲区尾部,从机应答或超时后,从环形缓冲区头部移除 6. 使用BootLoader+APP形式 需要两边对齐地址,只能烧写.bin文件 7. 使能USB功能,不需要USB功能时关闭使能,USB相关文件夹失能编译选项(右键文件夹 option->include target in build)(LVGL RTOS Fatfs如此) #### 安装教程 1. core_cm3.c 文件版本太老,初次建立工程或者安装Keil5式会报错,需要在targe里降低编译版本为5 1. xxxx 2. xxxx 3. xxxx #### 使用说明 STM32命名规则 C8T6: C: 48Pin 8: 64K Flash (中容量 64K - 128K 20K RAM) C:(256K - 512K 64K RAM) T: LQFP 6: 工作温度 任意I/O和控制引脚上的输出灌电流 25mA 端口总电流,如GPIOA 小于80mA,未在文档找到相应描述 总电流小于150mA #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request /********** 资源占用表 ***********************/ PIN 占用功能 附加占用 PA0 TIM2-PWM-ch1 PA1 PA2 UART2-TX DMA1-ch7 PA3 UART2-RX DMA1-ch6 PA4 PA5 SPI1-SCLK PA6 SPI1-MISO DMA1-ch2 PA7 SPI1-MOSI DMA1-ch3 PA8 PA9 UART1-TX DMA1-ch4 PA10 UART1-RX DMA1-ch5 PA11 USB DM- PA12 USB DP+ PA13 SWD PA14 SWD PA15 JLINK PB0 PB1 PB2 PB3 JLINK PB4 JLINK PB5 PB6 I2C1-SCL PB7 I2C1-SDA PB8 PB9 PB10 UART3-TX/I2C2-SCL DMA1-ch2 PB11 UART3-RX/I2C2-SDA DMA1-ch3 PB12 PB13 SPI2_SCK PB14 SPI2-MISO PB15 SPI2-MOSI PC13 LED心跳灯 PC14 PC15 /*******************************************/ /************** 地址占用表 *******************/ BootLoader 0x0800 0000 - 0x0800 3FFF 大小0x4000 APP 0x0800 4000 - 0x0800 7FFF 大小0x4000 修改system里的偏移量,ST给出该值为0x200倍数,对其中断向量表 /*******************************************/ /************** 中断分组表 *****************/ /*******************************************/ DMA1与外设的固定关系 DMA1 通道 绑定外设 CH1 ADC1 CH2 SPI1_RX / USART3_TX CH3 SPI1_TX / USART3_RX CH4 SPI2_RX / USART1_TX / I2c2_TX CH5 SPI2_TX / USART1_RX / I2C2_RX CH6 USART2_TX / I2C1_TX CH7 USART2_RX / I2C1_RX /*******************************************/ 外设初始化的良好顺序 GPIO_Init(GPIOA, &GPIO_InitStruct); DMA_Init(&DMA_InitStruct); USART_Init(USART1, &USART_InitStruct); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; NVIC_Init(&NVIC_InitStruct); DMA_SetCurrDataCounter(DMA1_Channel5, RX_BUF_LEN); DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE); USART_Cmd(USART1, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);