diff --git a/.opencode/skills/pdf-analyzer/SKILL.md b/.opencode/skills/pdf-analyzer/SKILL.md new file mode 100644 index 0000000..a7b433d --- /dev/null +++ b/.opencode/skills/pdf-analyzer/SKILL.md @@ -0,0 +1,134 @@ +--- +name: pdf-analyzer +description: 使用 MinerU API 读取并分析 PDF 文件,支持文件解析、表格/公式提取、OCR 识别、异步任务管理 +license: MIT +compatibility: opencode +metadata: + server: http://192.168.31.138:8312 +--- + +## 概述 + +通过 MinerU API (`http://192.168.31.138:8312`) 分析 PDF/图片/DOCX/PPTX/XLSX 文件。 + +## API 端点 + +### 1. 同步解析 `POST /file_parse` + +上传文件并等待解析完成,直接返回结果。 + +```bash +curl -X POST "http://192.168.31.138:8312/file_parse" \ + -F "files=@/path/to/document.pdf" \ + -F "lang_list=ch" \ + -F "backend=hybrid-auto-engine" \ + -F "parse_method=auto" \ + -F "formula_enable=true" \ + -F "table_enable=true" \ + -F "image_analysis=true" \ + -F "return_md=true" +``` + +### 2. 异步提交 `POST /tasks` + +提交解析任务,立即返回 `task_id`。 + +```bash +curl -X POST "http://192.168.31.138:8312/tasks" \ + -F "files=@/path/to/document.pdf" \ + -F "lang_list=ch" \ + -F "backend=hybrid-auto-engine" \ + -F "return_md=true" +``` + +### 3. 查询任务状态 `GET /tasks/{task_id}` + +```bash +curl "http://192.168.31.138:8312/tasks/{task_id}" +``` + +返回状态: `pending`, `running`, `completed`, `failed` + +### 4. 获取任务结果 `GET /tasks/{task_id}/result` + +```bash +curl "http://192.168.31.138:8312/tasks/{task_id}/result" +``` + +### 5. 健康检查 `GET /health` + +```bash +curl "http://192.168.31.138:8312/health" +``` + +## 参数说明 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `files` | array | 必填 | 上传 PDF/图片/DOCX/PPTX/XLSX 文件 | +| `lang_list` | array | `["ch"]` | OCR 语言: `ch`, `en`, `korean`, `japan`, `arabic`, `latin`, `cyrillic`, `devanagari` 等 | +| `backend` | string | `hybrid-auto-engine` | 解析后端: `pipeline`, `vlm-auto-engine`, `vlm-http-client`, `hybrid-auto-engine`, `hybrid-http-client` | +| `parse_method` | string | `auto` | 解析方法: `auto`, `txt`, `ocr`(仅 pipeline/hybrid) | +| `formula_enable` | bool | `true` | 是否解析公式 | +| `table_enable` | bool | `true` | 是否解析表格 | +| `image_analysis` | bool | `true` | 是否分析图片/图表(VLM/hybrid 后端) | +| `server_url` | string | null | OpenAI 兼容服务器 URL(仅 http-client 后端) | +| `return_md` | bool | `true` | 返回 Markdown 内容 | +| `return_middle_json` | bool | `false` | 返回中间 JSON | +| `return_model_output` | bool | `false` | 返回模型输出 JSON | +| `return_content_list` | bool | `false` | 返回内容列表 JSON | +| `return_images` | bool | `false` | 返回提取的图片 | +| `response_format_zip` | bool | `false` | 返回 ZIP 格式结果 | +| `return_original_file` | bool | `false` | ZIP 中包含原始文件 | +| `client_side_output_generation` | bool | `false` | 客户端生成最终输出 | +| `start_page_id` | int | 0 | 开始页码(从 0 开始) | +| `end_page_id` | int | 99999 | 结束页码(从 0 开始) | + +## Python 使用示例 + +```python +import requests + +API_BASE = "http://192.168.31.138:8312" + +# 同步解析 +with open("document.pdf", "rb") as f: + resp = requests.post(f"{API_BASE}/file_parse", files=[ + ("files", ("document.pdf", f, "application/pdf")) + ], data={ + "lang_list": ["ch", "en"], + "backend": "hybrid-auto-engine", + "formula_enable": True, + "table_enable": True, + "return_md": True, + "return_content_list": True + }) + result = resp.json() + print(result.get("md", "")) # Markdown 内容 + +# 异步解析 +with open("document.pdf", "rb") as f: + resp = requests.post(f"{API_BASE}/tasks", files=[ + ("files", ("document.pdf", f, "application/pdf")) + ], data={"return_md": True}) + task_id = resp.json()["task_id"] + +import time +while True: + status = requests.get(f"{API_BASE}/tasks/{task_id}").json() + if status["status"] in ("completed", "failed"): + break + time.sleep(2) + +result = requests.get(f"{API_BASE}/tasks/{task_id}/result").json() +``` + +## 使用场景 + +1. **PDF 转 Markdown** — 提取 PDF 内容为结构化 Markdown +2. **表格提取** — 从 PDF 中识别并提取表格数据 +3. **公式提取** — 提取数学公式(LaTeX 格式) +4. **图片分析** — 识别并分析 PDF 中的图片/图表 +5. **OCR 识别** — 扫描件/图片型 PDF 的文字识别 +6. **多语言文档** — 支持中文、英文、日文、韩文、阿拉伯语等多种语言 +7. **分页解析** — 通过 `start_page_id` / `end_page_id` 指定页码范围 diff --git a/AGENTS.md b/AGENTS.md index f20ecd4..edb1dd2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,26 +1,43 @@ -# STM32F103C8T6 Project +# STM32F103C8T6 项目 -## Project Type -STM32CubeMX-generated project using **Keil MDK-ARM V5.32** toolchain. +## 项目类型 +STM32CubeMX 生成的项目,使用 **Keil MDK-ARM V5.32** 工具链。 -## Key Files -- `STM32F103C8T6/STM32F103C8T6.ioc` — CubeMX configuration (pinout, clock, peripherals) -- `STM32F103C8T6/Core/Src/main.c` — Application entry point -- `STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx` — Keil project file +## 关键文件 +- `STM32F103C8T6/STM32F103C8T6.ioc` — CubeMX 配置(引脚、时钟、外设) +- `STM32F103C8T6/Core/Src/main.c` — 应用入口 +- `STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx` — Keil 工程文件 +- `STM32F103C8T6/Drivers/BSP/MultiButton/` — MultiButton 按键驱动库 +- `STM32F103C8T6/Drivers/BSP/LCD/` — ST7735S LCD 驱动 -## Hardware Configuration +## 硬件配置 - **MCU**: STM32F103C8T6 (LQFP48, 72MHz, 64KB Flash, 20KB RAM) -- **Clock**: HSE 8MHz → PLL ×9 = 72MHz SYSCLK -- **Peripherals**: - - USART1: PA9 (TX), PA10 (RX) — Async mode - - LED: PC13 (active low, pull-up) - - Keys: PB3 (KEY1), PB4 (KEY2), PB5 (KEY3), PC14 (KEY4), PC15 (KEY5) — Pull-down - - LCD: PB12 (RST), PB13 (SCL), PB15 (SDA) — GPIO output, pull-up +- **时钟**: HSE 8MHz → PLL ×9 = 72MHz SYSCLK +- **外设**: + - USART1: PA9 (TX), PA10 (RX) — 异步模式 + - SPI2: PB13 (SCK), PB15 (MOSI) — 18MHz, DMA1_Channel5 + - LED: PC13 (低电平有效,上拉) + - 按键: PB3 (KEY1), PB4 (KEY2), PB5 (KEY3), PC14 (KEY4), PC15 (KEY5) — 下拉 + - LCD: PB10 (DC), PB11 (CS), PB12 (RST), PB13 (SCK), PB15 (SDA) — ST7735S 128x160 -## Code Conventions -- Custom code must be placed within `/* USER CODE BEGIN */` and `/* USER CODE END */` markers -- Code outside these markers will be overwritten by CubeMX code generation -- HAL library is used (defined `USE_HAL_DRIVER` and `STM32F103xB`) +## MultiButton 按键库 +- **来源**: [0x1abin/MultiButton](https://github.com/0x1abin/MultiButton) +- **功能**: 事件驱动型按键驱动,支持单击、双击、长按、连击等事件 +- **文件**: + - `Drivers/BSP/MultiButton/multi_button.c/.h` — 核心库文件 + - `Drivers/BSP/MultiButton/button_driver.c/.h` — 本项目适配层 +- **定时器**: SysTick 中断中每5ms调用 `button_ticks()` +- **使用示例**: + ```c + /* 在回调函数中处理按键事件 */ + static void button_key1_callback(Button* handle, void* user_data) { + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + printf("KEY1: LED翻转\n"); + } + + /* 初始化时注册回调 */ + button_attach(&btn_handle, BTN_SINGLE_CLICK, button_key1_callback, NULL); + ``` ## 代码规范 - **遵循**: `嵌入式C语言代码规范(V1.0).md` @@ -33,7 +50,11 @@ STM32CubeMX-generated project using **Keil MDK-ARM V5.32** toolchain. - **大括号**: 所有if/for/while必须加大括号,左大括号同行,右大括号单独行 - **禁止**: goto、递归、可变参数函数、注释掉的代码提交 -## Important Notes -- `Drivers/` directory contains HAL driver source — do not edit directly -- Regenerate code via CubeMX `.ioc` file, not manually editing HAL files -- Keil build output goes to `MDK-ARM/STM32F103C8T6/` (already gitignored) +## 语言要求 +- 所有文档、注释、提交信息必须使用**中文** + +## 重要说明 +- `Drivers/` 目录包含 HAL 驱动源码 — 禁止直接修改 +- 通过 CubeMX `.ioc` 文件重新生成代码,禁止手动修改 HAL 文件 +- Keil 构建输出在 `MDK-ARM/STM32F103C8T6/`(已 gitignore) +- CubeMX 生成的代码中,自定义代码必须放在 `/* USER CODE BEGIN */` 和 `/* USER CODE END */` 之间 diff --git a/ST7735S_V1.1_20111121.pdf b/ST7735S_V1.1_20111121.pdf new file mode 100644 index 0000000..8f6bbb4 Binary files /dev/null and b/ST7735S_V1.1_20111121.pdf differ diff --git a/STM32F103C8T6/.mxproject b/STM32F103C8T6/.mxproject index 3e61986..159a0a0 100644 --- a/STM32F103C8T6/.mxproject +++ b/STM32F103C8T6/.mxproject @@ -1,29 +1,33 @@ +[PreviousLibFiles] +LibFiles=Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_spi.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_spi.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_spi.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_spi.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_spi.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f103xb.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; + +[PreviousUsedKeilFiles] +SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\dma.c;..\Core\Src\spi.c;..\Core\Src\usart.c;..\Core\Src\stm32f1xx_it.c;..\Core\Src\stm32f1xx_hal_msp.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_spi.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_spi.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;;; +HeaderPath=..\Drivers\STM32F1xx_HAL_Driver\Inc;..\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F1xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; +CDefines=USE_HAL_DRIVER;STM32F103xB;USE_HAL_DRIVER;USE_HAL_DRIVER; + [PreviousGenFiles] AdvancedFolderStructure=true -HeaderFileListSize=5 +HeaderFileListSize=7 HeaderFiles#0=..\Core\Inc\gpio.h -HeaderFiles#1=..\Core\Inc\usart.h -HeaderFiles#2=..\Core\Inc\stm32f1xx_it.h -HeaderFiles#3=..\Core\Inc\stm32f1xx_hal_conf.h -HeaderFiles#4=..\Core\Inc\main.h +HeaderFiles#1=..\Core\Inc\dma.h +HeaderFiles#2=..\Core\Inc\spi.h +HeaderFiles#3=..\Core\Inc\usart.h +HeaderFiles#4=..\Core\Inc\stm32f1xx_it.h +HeaderFiles#5=..\Core\Inc\stm32f1xx_hal_conf.h +HeaderFiles#6=..\Core\Inc\main.h HeaderFolderListSize=1 HeaderPath#0=..\Core\Inc HeaderFiles=; -SourceFileListSize=5 +SourceFileListSize=7 SourceFiles#0=..\Core\Src\gpio.c -SourceFiles#1=..\Core\Src\usart.c -SourceFiles#2=..\Core\Src\stm32f1xx_it.c -SourceFiles#3=..\Core\Src\stm32f1xx_hal_msp.c -SourceFiles#4=..\Core\Src\main.c +SourceFiles#1=..\Core\Src\dma.c +SourceFiles#2=..\Core\Src\spi.c +SourceFiles#3=..\Core\Src\usart.c +SourceFiles#4=..\Core\Src\stm32f1xx_it.c +SourceFiles#5=..\Core\Src\stm32f1xx_hal_msp.c +SourceFiles#6=..\Core\Src\main.c SourceFolderListSize=1 SourcePath#0=..\Core\Src SourceFiles=; -[PreviousLibFiles] -LibFiles=Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f103xb.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; - -[PreviousUsedKeilFiles] -SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\usart.c;..\Core\Src\stm32f1xx_it.c;..\Core\Src\stm32f1xx_hal_msp.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;..\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;..\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;..\Core\Src\system_stm32f1xx.c;;; -HeaderPath=..\Drivers\STM32F1xx_HAL_Driver\Inc;..\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F1xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; -CDefines=USE_HAL_DRIVER;STM32F103xB;USE_HAL_DRIVER;USE_HAL_DRIVER; - diff --git a/STM32F103C8T6/Core/Inc/dma.h b/STM32F103C8T6/Core/Inc/dma.h new file mode 100644 index 0000000..afad30d --- /dev/null +++ b/STM32F103C8T6/Core/Inc/dma.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.h + * @brief This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_H__ */ + diff --git a/STM32F103C8T6/Core/Inc/main.h b/STM32F103C8T6/Core/Inc/main.h index ea751ad..afaecc0 100644 --- a/STM32F103C8T6/Core/Inc/main.h +++ b/STM32F103C8T6/Core/Inc/main.h @@ -63,12 +63,12 @@ void Error_Handler(void); #define KEY4_GPIO_Port GPIOC #define KEY5_Pin GPIO_PIN_15 #define KEY5_GPIO_Port GPIOC +#define LCD_DC_Pin GPIO_PIN_10 +#define LCD_DC_GPIO_Port GPIOB +#define LCD_CS_Pin GPIO_PIN_11 +#define LCD_CS_GPIO_Port GPIOB #define LCD_RST_Pin GPIO_PIN_12 #define LCD_RST_GPIO_Port GPIOB -#define LCD_SCL_Pin GPIO_PIN_13 -#define LCD_SCL_GPIO_Port GPIOB -#define LCD_SDA_Pin GPIO_PIN_15 -#define LCD_SDA_GPIO_Port GPIOB #define KEY3_Pin GPIO_PIN_3 #define KEY3_GPIO_Port GPIOB #define KEY1_Pin GPIO_PIN_4 diff --git a/STM32F103C8T6/Core/Inc/spi.h b/STM32F103C8T6/Core/Inc/spi.h new file mode 100644 index 0000000..e95ad04 --- /dev/null +++ b/STM32F103C8T6/Core/Inc/spi.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file spi.h + * @brief This file contains all the function prototypes for + * the spi.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __SPI_H__ +#define __SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern SPI_HandleTypeDef hspi2; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_SPI2_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SPI_H__ */ + diff --git a/STM32F103C8T6/Core/Inc/stm32f1xx_hal_conf.h b/STM32F103C8T6/Core/Inc/stm32f1xx_hal_conf.h index e2fadb3..6dab2e3 100644 --- a/STM32F103C8T6/Core/Inc/stm32f1xx_hal_conf.h +++ b/STM32F103C8T6/Core/Inc/stm32f1xx_hal_conf.h @@ -42,7 +42,7 @@ /*#define HAL_CORTEX_MODULE_ENABLED */ /*#define HAL_CRC_MODULE_ENABLED */ /*#define HAL_DAC_MODULE_ENABLED */ -/*#define HAL_DMA_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED /*#define HAL_ETH_MODULE_ENABLED */ /*#define HAL_FLASH_MODULE_ENABLED */ #define HAL_GPIO_MODULE_ENABLED @@ -62,7 +62,7 @@ /*#define HAL_MMC_MODULE_ENABLED */ /*#define HAL_SDRAM_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */ -/*#define HAL_SPI_MODULE_ENABLED */ +#define HAL_SPI_MODULE_ENABLED /*#define HAL_SRAM_MODULE_ENABLED */ /*#define HAL_TIM_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED diff --git a/STM32F103C8T6/Core/Inc/stm32f1xx_it.h b/STM32F103C8T6/Core/Inc/stm32f1xx_it.h index 77bd330..05525eb 100644 --- a/STM32F103C8T6/Core/Inc/stm32f1xx_it.h +++ b/STM32F103C8T6/Core/Inc/stm32f1xx_it.h @@ -55,6 +55,7 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void DMA1_Channel5_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/STM32F103C8T6/Core/Src/dma.c b/STM32F103C8T6/Core/Src/dma.c new file mode 100644 index 0000000..1d6068c --- /dev/null +++ b/STM32F103C8T6/Core/Src/dma.c @@ -0,0 +1,55 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.c + * @brief This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Channel5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + diff --git a/STM32F103C8T6/Core/Src/gpio.c b/STM32F103C8T6/Core/Src/gpio.c index 2480eba..50ed216 100644 --- a/STM32F103C8T6/Core/Src/gpio.c +++ b/STM32F103C8T6/Core/Src/gpio.c @@ -54,7 +54,7 @@ void MX_GPIO_Init(void) HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(GPIOB, LCD_RST_Pin|LCD_SCL_Pin|LCD_SDA_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOB, LCD_DC_Pin|LCD_CS_Pin|LCD_RST_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : LED_Pin */ GPIO_InitStruct.Pin = LED_Pin; @@ -69,8 +69,8 @@ void MX_GPIO_Init(void) GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - /*Configure GPIO pins : LCD_RST_Pin LCD_SCL_Pin LCD_SDA_Pin */ - GPIO_InitStruct.Pin = LCD_RST_Pin|LCD_SCL_Pin|LCD_SDA_Pin; + /*Configure GPIO pins : LCD_DC_Pin LCD_CS_Pin LCD_RST_Pin */ + GPIO_InitStruct.Pin = LCD_DC_Pin|LCD_CS_Pin|LCD_RST_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; diff --git a/STM32F103C8T6/Core/Src/main.c b/STM32F103C8T6/Core/Src/main.c index aad8b0d..eb7cc91 100644 --- a/STM32F103C8T6/Core/Src/main.c +++ b/STM32F103C8T6/Core/Src/main.c @@ -18,12 +18,16 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" +#include "dma.h" +#include "spi.h" #include "usart.h" #include "gpio.h" - +#include "lcd_data.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include +#include "button_driver.h" +#include "st7735s.h" /* USER CODE END Includes */ @@ -87,9 +91,21 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); MX_USART1_UART_Init(); + MX_SPI2_Init(); /* USER CODE BEGIN 2 */ - + printf("\r\nSTM32F103C8T6 Boot OK\r\n"); + button_driver_init(); + st7735s_init(); + st7735s_fill_screen(COLOR_RED); + HAL_Delay(500); + st7735s_fill_screen(COLOR_GREEN); + HAL_Delay(500); + st7735s_fill_screen(COLOR_BLUE); + HAL_Delay(500); + st7735s_fill_screen(COLOR_BLACK); + st7735s_draw_string(0, 0, "LCD OK", COLOR_WHITE, COLOR_BLACK); /* USER CODE END 2 */ /* Infinite loop */ @@ -101,7 +117,7 @@ int main(void) /* USER CODE BEGIN 3 */ HAL_Delay(500); HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); - printf("Hello word\n"); + //printf("Hello word\n"); } /* USER CODE END 3 */ } diff --git a/STM32F103C8T6/Core/Src/spi.c b/STM32F103C8T6/Core/Src/spi.c new file mode 100644 index 0000000..abe913e --- /dev/null +++ b/STM32F103C8T6/Core/Src/spi.c @@ -0,0 +1,136 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file spi.c + * @brief This file provides code for the configuration + * of the SPI instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "spi.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +SPI_HandleTypeDef hspi2; +DMA_HandleTypeDef hdma_spi2_tx; + +/* SPI2 init function */ +void MX_SPI2_Init(void) +{ + + /* USER CODE BEGIN SPI2_Init 0 */ + + /* USER CODE END SPI2_Init 0 */ + + /* USER CODE BEGIN SPI2_Init 1 */ + + /* USER CODE END SPI2_Init 1 */ + hspi2.Instance = SPI2; + hspi2.Init.Mode = SPI_MODE_MASTER; + hspi2.Init.Direction = SPI_DIRECTION_2LINES; + hspi2.Init.DataSize = SPI_DATASIZE_8BIT; + hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi2.Init.NSS = SPI_NSS_SOFT; + hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi2.Init.TIMode = SPI_TIMODE_DISABLE; + hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi2.Init.CRCPolynomial = 10; + if (HAL_SPI_Init(&hspi2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN SPI2_Init 2 */ + + /* USER CODE END SPI2_Init 2 */ + +} + +void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(spiHandle->Instance==SPI2) + { + /* USER CODE BEGIN SPI2_MspInit 0 */ + + /* USER CODE END SPI2_MspInit 0 */ + /* SPI2 clock enable */ + __HAL_RCC_SPI2_CLK_ENABLE(); + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**SPI2 GPIO Configuration + PB13 ------> SPI2_SCK + PB15 ------> SPI2_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* SPI2 DMA Init */ + /* SPI2_TX Init */ + hdma_spi2_tx.Instance = DMA1_Channel5; + hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi2_tx.Init.Mode = DMA_NORMAL; + hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx); + + /* USER CODE BEGIN SPI2_MspInit 1 */ + + /* USER CODE END SPI2_MspInit 1 */ + } +} + +void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) +{ + + if(spiHandle->Instance==SPI2) + { + /* USER CODE BEGIN SPI2_MspDeInit 0 */ + + /* USER CODE END SPI2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_SPI2_CLK_DISABLE(); + + /**SPI2 GPIO Configuration + PB13 ------> SPI2_SCK + PB15 ------> SPI2_MOSI + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_15); + + /* SPI2 DMA DeInit */ + HAL_DMA_DeInit(spiHandle->hdmatx); + /* USER CODE BEGIN SPI2_MspDeInit 1 */ + + /* USER CODE END SPI2_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + diff --git a/STM32F103C8T6/Core/Src/stm32f1xx_it.c b/STM32F103C8T6/Core/Src/stm32f1xx_it.c index 540ecf4..dd79f4e 100644 --- a/STM32F103C8T6/Core/Src/stm32f1xx_it.c +++ b/STM32F103C8T6/Core/Src/stm32f1xx_it.c @@ -22,6 +22,8 @@ #include "stm32f1xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "multi_button.h" + /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -41,7 +43,7 @@ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ - +static uint8_t s_button_tick_counter = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -55,7 +57,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ - +extern DMA_HandleTypeDef hdma_spi2_tx; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -188,6 +190,13 @@ void SysTick_Handler(void) HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ + /* 每5ms调用一次button_ticks() */ + s_button_tick_counter++; + if (s_button_tick_counter >= 5) { + s_button_tick_counter = 0; + button_ticks(); + } + /* USER CODE END SysTick_IRQn 1 */ } @@ -198,6 +207,20 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f1xx.s). */ /******************************************************************************/ +/** + * @brief This function handles DMA1 channel5 global interrupt. + */ +void DMA1_Channel5_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */ + + /* USER CODE END DMA1_Channel5_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_spi2_tx); + /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */ + + /* USER CODE END DMA1_Channel5_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c new file mode 100644 index 0000000..bf6d907 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c @@ -0,0 +1,297 @@ +#include "lcd_data.h" +/*ASCII字模数据*********************/ + +/*宽8像素,高16像素*/ +const uint8_t LCD_F8x16[][16] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 + 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,// ! 1 + 0x00,0x16,0x0E,0x00,0x16,0x0E,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// " 2 + 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00, + 0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,// # 3 + 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00, + 0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,// $ 4 + 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00, + 0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,// % 5 + 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00, + 0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,// & 6 + 0x00,0x00,0x00,0x16,0x0E,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// ' 7 + 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00, + 0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,// ( 8 + 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00, + 0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,// ) 9 + 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00, + 0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,// * 10 + 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, + 0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,// + 11 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,// , 12 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,// - 13 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,// . 14 + 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04, + 0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,// / 15 + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, + 0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,// 0 16 + 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,// 1 17 + 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00, + 0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,// 2 18 + 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00, + 0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,// 3 19 + 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00, + 0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,// 4 20 + 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00, + 0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,// 5 21 + 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00, + 0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,// 6 22 + 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00, + 0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,// 7 23 + 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00, + 0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,// 8 24 + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00, + 0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,// 9 25 + 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,// : 26 + 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00, + 0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,// ; 27 + 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00, + 0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,// < 28 + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,// = 29 + 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00, + 0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,// > 30 + 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00, + 0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,// ? 31 + 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00, + 0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,// @ 32 + 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00, + 0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,// A 33 + 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,// B 34 + 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00, + 0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,// C 35 + 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,// D 36 + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, + 0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,// E 37 + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, + 0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,// F 38 + 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00, + 0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,// G 39 + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, + 0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,// H 40 + 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,// I 41 + 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00, + 0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,// J 42 + 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00, + 0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,// K 43 + 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00, + 0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,// L 44 + 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00, + 0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,// M 45 + 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08, + 0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,// N 46 + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,// O 47 + 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00, + 0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,// P 48 + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00, + 0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,// Q 49 + 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00, + 0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,// R 50 + 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00, + 0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,// S 51 + 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00, + 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,// T 52 + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08, + 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,// U 53 + 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08, + 0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,// V 54 + 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00, + 0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,// W 55 + 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08, + 0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,// X 56 + 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00, + 0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,// Y 57 + 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00, + 0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,// Z 58 + 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00, + 0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,// [ 59 + 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,// \ 60 + 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00, + 0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,// ] 61 + 0x00,0x20,0x10,0x08,0x04,0x08,0x10,0x20, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// ^ 62 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,// _ 63 + 0x00,0x02,0x04,0x08,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// ` 64 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,// a 65 + 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00, + 0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,// b 66 + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, + 0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,// c 67 + 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00, + 0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,// d 68 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,// e 69 + 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,// f 70 + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,// g 71 + 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00, + 0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,// h 72 + 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,// i 73 + 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00, + 0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,// j 74 + 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00, + 0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,// k 75 + 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,// l 76 + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + 0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,// m 77 + 0x00,0x80,0x80,0x00,0x80,0x80,0x00,0x00, + 0x00,0x20,0x3F,0x21,0x00,0x20,0x3F,0x20,// n 78 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00, + 0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,// o 79 + 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00, + 0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,// p 80 + 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00, + 0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,// q 81 + 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00, + 0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,// r 82 + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,// s 83 + 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00, + 0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,// t 84 + 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00, + 0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,// u 85 + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, + 0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,// v 86 + 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80, + 0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,// w 87 + 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00, + 0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,// x 88 + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80, + 0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,// y 89 + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + 0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,// z 90 + 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02, + 0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,// { 91 + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,// | 92 + 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00, + 0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,// } 93 + 0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x80, + 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,// ~ 94 +}; + +/*宽6像素,高8像素*/ +const uint8_t LCD_F6x8[][6] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,// 0 + 0x00,0x00,0x00,0x2F,0x00,0x00,// ! 1 + 0x00,0x00,0x07,0x00,0x07,0x00,// " 2 + 0x00,0x14,0x7F,0x14,0x7F,0x14,// # 3 + 0x00,0x24,0x2A,0x7F,0x2A,0x12,// $ 4 + 0x00,0x23,0x13,0x08,0x64,0x62,// % 5 + 0x00,0x36,0x49,0x55,0x22,0x50,// & 6 + 0x00,0x00,0x00,0x07,0x00,0x00,// ' 7 + 0x00,0x00,0x1C,0x22,0x41,0x00,// ( 8 + 0x00,0x00,0x41,0x22,0x1C,0x00,// ) 9 + 0x00,0x14,0x08,0x3E,0x08,0x14,// * 10 + 0x00,0x08,0x08,0x3E,0x08,0x08,// + 11 + 0x00,0x00,0x00,0xA0,0x60,0x00,// , 12 + 0x00,0x08,0x08,0x08,0x08,0x08,// - 13 + 0x00,0x00,0x60,0x60,0x00,0x00,// . 14 + 0x00,0x20,0x10,0x08,0x04,0x02,// / 15 + 0x00,0x3E,0x51,0x49,0x45,0x3E,// 0 16 + 0x00,0x00,0x42,0x7F,0x40,0x00,// 1 17 + 0x00,0x42,0x61,0x51,0x49,0x46,// 2 18 + 0x00,0x21,0x41,0x45,0x4B,0x31,// 3 19 + 0x00,0x18,0x14,0x12,0x7F,0x10,// 4 20 + 0x00,0x27,0x45,0x45,0x45,0x39,// 5 21 + 0x00,0x3C,0x4A,0x49,0x49,0x30,// 6 22 + 0x00,0x01,0x71,0x09,0x05,0x03,// 7 23 + 0x00,0x36,0x49,0x49,0x49,0x36,// 8 24 + 0x00,0x06,0x49,0x49,0x29,0x1E,// 9 25 + 0x00,0x00,0x36,0x36,0x00,0x00,// : 26 + 0x00,0x00,0x56,0x36,0x00,0x00,// ; 27 + 0x00,0x08,0x14,0x22,0x41,0x00,// < 28 + 0x00,0x14,0x14,0x14,0x14,0x14,// = 29 + 0x00,0x00,0x41,0x22,0x14,0x08,// > 30 + 0x00,0x02,0x01,0x51,0x09,0x06,// ? 31 + 0x00,0x3E,0x49,0x55,0x59,0x2E,// @ 32 + 0x00,0x7C,0x12,0x11,0x12,0x7C,// A 33 + 0x00,0x7F,0x49,0x49,0x49,0x36,// B 34 + 0x00,0x3E,0x41,0x41,0x41,0x22,// C 35 + 0x00,0x7F,0x41,0x41,0x22,0x1C,// D 36 + 0x00,0x7F,0x49,0x49,0x49,0x41,// E 37 + 0x00,0x7F,0x09,0x09,0x09,0x01,// F 38 + 0x00,0x3E,0x41,0x49,0x49,0x7A,// G 39 + 0x00,0x7F,0x08,0x08,0x08,0x7F,// H 40 + 0x00,0x00,0x41,0x7F,0x41,0x00,// I 41 + 0x00,0x20,0x40,0x41,0x3F,0x01,// J 42 + 0x00,0x7F,0x08,0x14,0x22,0x41,// K 43 + 0x00,0x7F,0x40,0x40,0x40,0x40,// L 44 + 0x00,0x7F,0x02,0x0C,0x02,0x7F,// M 45 + 0x00,0x7F,0x04,0x08,0x10,0x7F,// N 46 + 0x00,0x3E,0x41,0x41,0x41,0x3E,// O 47 + 0x00,0x7F,0x09,0x09,0x09,0x06,// P 48 + 0x00,0x3E,0x41,0x51,0x21,0x5E,// Q 49 + 0x00,0x7F,0x09,0x19,0x29,0x46,// R 50 + 0x00,0x46,0x49,0x49,0x49,0x31,// S 51 + 0x00,0x01,0x01,0x7F,0x01,0x01,// T 52 + 0x00,0x3F,0x40,0x40,0x40,0x3F,// U 53 + 0x00,0x1F,0x20,0x40,0x20,0x1F,// V 54 + 0x00,0x3F,0x40,0x38,0x40,0x3F,// W 55 + 0x00,0x63,0x14,0x08,0x14,0x63,// X 56 + 0x00,0x07,0x08,0x70,0x08,0x07,// Y 57 + 0x00,0x61,0x51,0x49,0x45,0x43,// Z 58 + 0x00,0x00,0x7F,0x41,0x41,0x00,// [ 59 + 0x00,0x02,0x04,0x08,0x10,0x20,// \ 60 + 0x00,0x00,0x41,0x41,0x7F,0x00,// ] 61 + 0x00,0x04,0x02,0x01,0x02,0x04,// ^ 62 + 0x00,0x40,0x40,0x40,0x40,0x40,// _ 63 + 0x00,0x00,0x01,0x02,0x04,0x00,// ` 64 + 0x00,0x20,0x54,0x54,0x54,0x78,// a 65 + 0x00,0x7F,0x48,0x44,0x44,0x38,// b 66 + 0x00,0x38,0x44,0x44,0x44,0x20,// c 67 + 0x00,0x38,0x44,0x44,0x48,0x7F,// d 68 + 0x00,0x38,0x54,0x54,0x54,0x18,// e 69 + 0x00,0x08,0x7E,0x09,0x01,0x02,// f 70 + 0x00,0x18,0xA4,0xA4,0xA4,0x7C,// g 71 + 0x00,0x7F,0x08,0x04,0x04,0x78,// h 72 + 0x00,0x00,0x44,0x7D,0x40,0x00,// i 73 + 0x00,0x40,0x80,0x84,0x7D,0x00,// j 74 + 0x00,0x7F,0x10,0x28,0x44,0x00,// k 75 + 0x00,0x00,0x41,0x7F,0x40,0x00,// l 76 + 0x00,0x7C,0x04,0x18,0x04,0x78,// m 77 + 0x00,0x7C,0x08,0x04,0x04,0x78,// n 78 + 0x00,0x38,0x44,0x44,0x44,0x38,// o 79 + 0x00,0xFC,0x24,0x24,0x24,0x18,// p 80 + 0x00,0x18,0x24,0x24,0x18,0xFC,// q 81 + 0x00,0x7C,0x08,0x04,0x04,0x08,// r 82 + 0x00,0x48,0x54,0x54,0x54,0x20,// s 83 + 0x00,0x04,0x3F,0x44,0x40,0x20,// t 84 + 0x00,0x3C,0x40,0x40,0x20,0x7C,// u 85 + 0x00,0x1C,0x20,0x40,0x20,0x1C,// v 86 + 0x00,0x3C,0x40,0x30,0x40,0x3C,// w 87 + 0x00,0x44,0x28,0x10,0x28,0x44,// x 88 + 0x00,0x1C,0xA0,0xA0,0xA0,0x7C,// y 89 + 0x00,0x44,0x64,0x54,0x4C,0x44,// z 90 + 0x00,0x00,0x08,0x7F,0x41,0x00,// { 91 + 0x00,0x00,0x00,0x7F,0x00,0x00,// | 92 + 0x00,0x00,0x41,0x7F,0x08,0x00,// } 93 + 0x00,0x08,0x04,0x08,0x10,0x08,// ~ 94 +}; diff --git a/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.h b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.h new file mode 100644 index 0000000..02e67c0 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.h @@ -0,0 +1,10 @@ +#ifndef __LCD_DATA_H_ +#define __LCD_DATA_H_ + +#include + +/*ASCII字模数据声明*/ +extern const uint8_t LCD_F8x16[][16]; +extern const uint8_t LCD_F6x8[][6]; + +#endif diff --git a/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c new file mode 100644 index 0000000..4628be2 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c @@ -0,0 +1,621 @@ +/* + * 模块名称:ST7735S LCD驱动 + * 模块功能:提供128x160 RGB TFT屏幕的初始化、画点、画线、填充、显示字符串等功能 + * 适用平台:STM32F103C8T6 + SPI2 + * 作者:王建锋 + * 创建日期:2026-07-13 + * 修改记录: + * 2026-07-13 王建锋 创建初始版本 + */ + +#include "st7735s.h" +#include "lcd_data.h" +#include "spi.h" +#include +#include + +static uint16_t s_lcd_width = LCD_WIDTH; +static uint16_t s_lcd_height = LCD_HEIGHT; + +extern DMA_HandleTypeDef hdma_spi2_tx; + +/* 8x16 ASCII字体(ASCII 32-126),每字符16字节 - 定义在 lcd_data.c 中 */ + +/* + * 函数功能:软件SPI写一个字节 + * 入口参数:data - 要发送的数据 + * 返回值:无 + * 函数说明:模拟SPI时序发送一个字节,MSB先 + */ +static void st7735s_spi_write_byte(uint8_t data) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + HAL_GPIO_WritePin(LCD_SCL_PORT, LCD_SCL_PIN, GPIO_PIN_RESET); + if (data & 0x80) { + HAL_GPIO_WritePin(LCD_SDA_PORT, LCD_SDA_PIN, GPIO_PIN_SET); + } else { + HAL_GPIO_WritePin(LCD_SDA_PORT, LCD_SDA_PIN, GPIO_PIN_RESET); + } + __NOP(); + __NOP(); + HAL_GPIO_WritePin(LCD_SCL_PORT, LCD_SCL_PIN, GPIO_PIN_SET); + __NOP(); + __NOP(); + data <<= 1; + } +} + +/* + * 函数功能:写入命令 + * 入口参数:cmd - 命令字节 + * 返回值:无 + * 函数说明:拉低DC,选择芯片,发送命令,释放芯片 + */ +static void st7735s_write_cmd(uint8_t cmd) +{ + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_RESET); + st7735s_spi_write_byte(cmd); + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); +} + +/* + * 函数功能:写入数据 + * 入口参数:data - 数据字节 + * 返回值:无 + * 函数说明:拉高DC,选择芯片,发送数据,释放芯片 + */ +static void st7735s_write_data(uint8_t data) +{ + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET); + st7735s_spi_write_byte(data); + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); +} + +/* + * 函数功能:写入多字节数据(CS保持低) + * 入口参数:p_data - 数据缓冲区指针 + * len - 字节数 + * 返回值:无 + * 函数说明:用于连续写入多个数据字节,省去中间CS跳变 + */ +static void st7735s_write_data_multi(const uint8_t *p_data, uint16_t len) +{ + uint16_t i; + + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET); + for (i = 0; i < len; i++) { + st7735s_spi_write_byte(p_data[i]); + } + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); +} + +/* + * 函数功能:写入16位颜色数据 + * 入口参数:p_color - 16位颜色缓冲区指针 + * len - 像素个数 + * 返回值:无 + * 函数说明:MSB先发送RGB565数据 + */ +static void st7735s_write_colors(uint16_t *p_color, uint16_t len) +{ + uint16_t i; + + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET); + for (i = 0; i < len; i++) { + st7735s_spi_write_byte((uint8_t)(p_color[i] >> 8)); + st7735s_spi_write_byte((uint8_t)(p_color[i] & 0xFF)); + } + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); +} + +/* + * 函数功能:LCD初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:执行ST7735S标准初始化序列 + */ +void st7735s_init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + printf("LCD init start (soft SPI)...\r\n"); + + /* 将SCL和SDA引脚切换为GPIO输出(软件SPI) */ + GPIO_InitStruct.Pin = LCD_SCL_PIN | LCD_SDA_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + HAL_GPIO_WritePin(LCD_SCL_PORT, LCD_SCL_PIN, GPIO_PIN_SET); + HAL_GPIO_WritePin(LCD_SDA_PORT, LCD_SDA_PIN, GPIO_PIN_SET); + + /* 确保CS和RST初始为高,避免LCD在初始化期间被错误选中 */ + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); + HAL_GPIO_WritePin(LCD_RST_PORT, LCD_RST_PIN, GPIO_PIN_SET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_RESET); + HAL_Delay(10); + + printf("IO: RST=%d DC=%d CS=%d\r\n", + (int)HAL_GPIO_ReadPin(LCD_RST_PORT, LCD_RST_PIN), + (int)HAL_GPIO_ReadPin(LCD_DC_PORT, LCD_DC_PIN), + (int)HAL_GPIO_ReadPin(LCD_CS_PORT, LCD_CS_PIN)); + + /* 硬件复位 */ + printf("HW reset...\r\n"); + HAL_GPIO_WritePin(LCD_RST_PORT, LCD_RST_PIN, GPIO_PIN_RESET); + HAL_Delay(10); + HAL_GPIO_WritePin(LCD_RST_PORT, LCD_RST_PIN, GPIO_PIN_SET); + HAL_Delay(120); + + /* 软件复位 */ + printf("SW reset...\r\n"); + st7735s_write_cmd(LCD_CMD_SWRESET); + HAL_Delay(150); + + /* 退出睡眠模式 */ + printf("Sleep out...\r\n"); + st7735s_write_cmd(LCD_CMD_SLPOUT); + HAL_Delay(500); + + /* 帧率控制 */ + printf("Frame rate...\r\n"); + st7735s_write_cmd(LCD_CMD_FRMCTR1); + st7735s_write_data(0x01); + st7735s_write_data(0x2C); + st7735s_write_data(0x2D); + + st7735s_write_cmd(LCD_CMD_FRMCTR2); + st7735s_write_data(0x01); + st7735s_write_data(0x2C); + st7735s_write_data(0x2D); + + st7735s_write_cmd(LCD_CMD_FRMCTR3); + st7735s_write_data(0x01); + st7735s_write_data(0x2C); + st7735s_write_data(0x2D); + st7735s_write_data(0x01); + st7735s_write_data(0x2C); + st7735s_write_data(0x2D); + + /* 显示反转控制 */ + st7735s_write_cmd(LCD_CMD_INVCTR); + st7735s_write_data(0x07); + + /* 功率控制 */ + printf("Power ctrl...\r\n"); + st7735s_write_cmd(LCD_CMD_PWCTR1); + st7735s_write_data(0xA2); + st7735s_write_data(0x02); + st7735s_write_data(0x84); + + st7735s_write_cmd(LCD_CMD_PWCTR2); + st7735s_write_data(0xC5); + + st7735s_write_cmd(LCD_CMD_PWCTR3); + st7735s_write_data(0x0A); + st7735s_write_data(0x00); + + st7735s_write_cmd(LCD_CMD_PWCTR4); + st7735s_write_data(0x8A); + st7735s_write_data(0x2A); + + st7735s_write_cmd(LCD_CMD_PWCTR5); + st7735s_write_data(0x8A); + st7735s_write_data(0xEE); + + /* VCOM控制 */ + st7735s_write_cmd(LCD_CMD_VMCTR1); + st7735s_write_data(0x0E); + + /* 竖屏模式 */ + printf("MADCTL...\r\n"); + st7735s_write_cmd(LCD_CMD_MADCTL); + st7735s_write_data(0xC8); + + /* 像素格式: 16位RGB565 */ + printf("COLMOD...\r\n"); + st7735s_write_cmd(LCD_CMD_COLMOD); + st7735s_write_data(0x05); + + /* Gamma校正 */ + printf("Gamma...\r\n"); + st7735s_write_cmd(LCD_CMD_GMCTRP1); + st7735s_write_data(0x02); + st7735s_write_data(0x1C); + st7735s_write_data(0x07); + st7735s_write_data(0x12); + st7735s_write_data(0x37); + st7735s_write_data(0x32); + st7735s_write_data(0x29); + st7735s_write_data(0x2D); + st7735s_write_data(0x29); + st7735s_write_data(0x25); + st7735s_write_data(0x2B); + st7735s_write_data(0x39); + st7735s_write_data(0x00); + st7735s_write_data(0x01); + st7735s_write_data(0x03); + st7735s_write_data(0x10); + + st7735s_write_cmd(LCD_CMD_GMCTRN1); + st7735s_write_data(0x03); + st7735s_write_data(0x1D); + st7735s_write_data(0x07); + st7735s_write_data(0x06); + st7735s_write_data(0x2E); + st7735s_write_data(0x2C); + st7735s_write_data(0x29); + st7735s_write_data(0x2D); + st7735s_write_data(0x2E); + st7735s_write_data(0x2E); + st7735s_write_data(0x37); + st7735s_write_data(0x3F); + st7735s_write_data(0x00); + st7735s_write_data(0x00); + st7735s_write_data(0x02); + st7735s_write_data(0x10); + + /* 关闭反转 */ + st7735s_write_cmd(0x20); + + /* 进入正常显示模式(关键!) */ + printf("NORON...\r\n"); + st7735s_write_cmd(0x13); + HAL_Delay(10); + + /* 开启显示 */ + printf("DISPON...\r\n"); + st7735s_write_cmd(LCD_CMD_DISPON); + HAL_Delay(100); + printf("LCD init done\r\n"); +} + +/* + * 函数功能:设置显示窗口 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * 返回值:无 + * 函数说明:设置后续写入操作的窗口区域 + */ +void st7735s_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) +{ + st7735s_write_cmd(LCD_CMD_CASET); + st7735s_write_data(0x00); + st7735s_write_data((uint8_t)x1); + st7735s_write_data(0x00); + st7735s_write_data((uint8_t)x2); + + st7735s_write_cmd(LCD_CMD_RASET); + st7735s_write_data(0x00); + st7735s_write_data((uint8_t)y1); + st7735s_write_data(0x00); + st7735s_write_data((uint8_t)y2); + + st7735s_write_cmd(LCD_CMD_RAMWR); +} + +/* + * 函数功能:填充矩形区域 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * color - 填充颜色 (RGB565) + * 返回值:无 + * 函数说明:用指定颜色填充矩形区域 + */ +void st7735s_fill_rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + uint32_t pixel_count; + uint16_t i; + uint16_t buf[64]; + + if (x1 > x2) { + uint16_t t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + uint16_t t = y1; + y1 = y2; + y2 = t; + } + + pixel_count = (uint32_t)(x2 - x1 + 1) * (y2 - y1 + 1); + + /* 预填充颜色缓冲区 */ + for (i = 0; i < 64; i++) { + buf[i] = color; + } + + st7735s_set_window(x1, y1, x2, y2); + + /* 分块发送 */ + while (pixel_count >= 64) { + st7735s_write_colors(buf, 64); + pixel_count -= 64; + } + if (pixel_count > 0) { + st7735s_write_colors(buf, (uint16_t)pixel_count); + } +} + +/* + * 函数功能:全屏填充 + * 入口参数:color - 填充颜色 (RGB565) + * 返回值:无 + * 函数说明:用指定颜色填充整个屏幕 + */ +void st7735s_fill_screen(uint16_t color) +{ + printf("fill_screen 0x%04X\r\n", color); + st7735s_fill_rect(0, 0, s_lcd_width - 1, s_lcd_height - 1, color); +} + +/* + * 函数功能:画点 + * 入口参数:x - 列坐标 + * y - 行坐标 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置画一个点 + */ +void st7735s_draw_pixel(uint16_t x, uint16_t y, uint16_t color) +{ + if (x >= s_lcd_width || y >= s_lcd_height) { + return; + } + st7735s_set_window(x, y, x, y); + st7735s_write_data((uint8_t)(color >> 8)); + st7735s_write_data((uint8_t)color); +} + +/* + * 函数功能:画线 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一条直线(Bresenham算法) + */ +void st7735s_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + int16_t dx; + int16_t dy; + int16_t sx; + int16_t sy; + int16_t err; + int16_t e2; + uint16_t x; + uint16_t y; + + if (x1 == x2) { + /* 垂直线 */ + if (y1 > y2) { + y = y1; + y1 = y2; + y2 = y; + } + st7735s_fill_rect(x1, y1, x1, y2, color); + return; + } + + if (y1 == y2) { + /* 水平线 */ + if (x1 > x2) { + x = x1; + x1 = x2; + x2 = x; + } + st7735s_fill_rect(x1, y1, x2, y1, color); + return; + } + + dx = (int16_t)x2 - (int16_t)x1; + if (dx < 0) { + dx = -dx; + } + sx = x1 < x2 ? 1 : -1; + dy = (int16_t)y2 - (int16_t)y1; + if (dy < 0) { + dy = -dy; + } + sy = y1 < y2 ? 1 : -1; + err = (dx > dy ? dx : -dy) / 2; + + x = x1; + y = y1; + + while (1) { + st7735s_draw_pixel(x, y, color); + if (x == x2 && y == y2) { + break; + } + e2 = err; + if (e2 > -dx) { + err -= dy; + x += sx; + } + if (e2 < dy) { + err += dx; + y += sy; + } + } +} + +/* + * 函数功能:画矩形 + * 入口参数:x - 左上角列 + * y - 左上角行 + * width - 宽度 + * height - 高度 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一个空心矩形 + */ +void st7735s_draw_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) +{ + st7735s_draw_line(x, y, x + width - 1, y, color); + st7735s_draw_line(x, y + height - 1, x + width - 1, y + height - 1, color); + st7735s_draw_line(x, y, x, y + height - 1, color); + st7735s_draw_line(x + width - 1, y, x + width - 1, y + height - 1, color); +} + +/* + * 函数功能:画圆 + * 入口参数:x0 - 圆心列 + * y0 - 圆心行 + * radius - 半径 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一个空心圆(Bresenham算法) + */ +void st7735s_draw_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t color) +{ + int16_t f = 1 - radius; + int16_t ddf_x = 1; + int16_t ddf_y = -2 * radius; + int16_t x = 0; + int16_t y = radius; + + st7735s_draw_pixel(x0, y0 + radius, color); + st7735s_draw_pixel(x0, y0 - radius, color); + st7735s_draw_pixel(x0 + radius, y0, color); + st7735s_draw_pixel(x0 - radius, y0, color); + + while (x < y) { + if (f >= 0) { + y--; + ddf_y += 2; + f += ddf_y; + } + x++; + ddf_x += 2; + f += ddf_x; + + st7735s_draw_pixel(x0 + x, y0 + y, color); + st7735s_draw_pixel(x0 - x, y0 + y, color); + st7735s_draw_pixel(x0 + x, y0 - y, color); + st7735s_draw_pixel(x0 - x, y0 - y, color); + st7735s_draw_pixel(x0 + y, y0 + x, color); + st7735s_draw_pixel(x0 - y, y0 + x, color); + st7735s_draw_pixel(x0 + y, y0 - x, color); + st7735s_draw_pixel(x0 - y, y0 - x, color); + } +} + +/* + * 函数功能:显示字符 + * 入口参数:x - 列坐标 + * y - 行坐标 + * ch - 字符 (ASCII 32-126) + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置显示一个8x16 ASCII字符 + */ +void st7735s_draw_char(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_color) +{ + uint16_t i; + uint16_t j; + uint8_t line; + + if (ch < 32 || ch > 126) { + ch = ' '; + } + + for (i = 0; i < 16; i++) { + line = LCD_F8x16[ch - 32][i]; + for (j = 0; j < 8; j++) { + if (line & 0x80) { + st7735s_draw_pixel(x + j, y + i, color); + } else { + st7735s_draw_pixel(x + j, y + i, bg_color); + } + line <<= 1; + } + } +} + +/* + * 函数功能:显示字符串 + * 入口参数:x - 列坐标 + * y - 行坐标 + * str - 字符串指针 + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置显示字符串 + */ +void st7735s_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color) +{ + while (*str) { + if (x + 8 > s_lcd_width) { + x = 0; + y += 16; + } + if (y + 16 > s_lcd_height) { + break; + } + st7735s_draw_char(x, y, *str, color, bg_color); + x += FONT_WIDTH_8; + str++; + } +} + +/* + * 函数功能:设置屏幕方向 + * 入口参数:rotation - 方向 (0-3) + * 返回值:无 + * 函数说明:0:竖屏 1:横屏 2:竖屏反转 3:横屏反转 + */ +void st7735s_set_rotation(uint8_t rotation) +{ + st7735s_write_cmd(LCD_CMD_MADCTL); + switch (rotation) { + case 0: + st7735s_write_data(0xC8); + s_lcd_width = 128; + s_lcd_height = 160; + break; + case 1: + st7735s_write_data(0x78); + s_lcd_width = 160; + s_lcd_height = 128; + break; + case 2: + st7735s_write_data(0x08); + s_lcd_width = 128; + s_lcd_height = 160; + break; + case 3: + st7735s_write_data(0xA8); + s_lcd_width = 160; + s_lcd_height = 128; + break; + default: + break; + } +} + +/* + * 函数功能:设置背光 + * 入口参数:state - 1:开 0:关 + * 返回值:无 + * 函数说明:控制LCD背光(如有硬件背光控制) + */ +void st7735s_backlight(uint8_t state) +{ + (void)state; + /* 当前硬件未连接背光控制引脚,预留接口 */ +} diff --git a/STM32F103C8T6/Drivers/BSP/LCD/st7735s.h b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.h new file mode 100644 index 0000000..c13a4f2 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.h @@ -0,0 +1,213 @@ +/* + * 模块名称:ST7735S LCD驱动 + * 模块功能:提供128x160 RGB TFT屏幕的初始化、画点、画线、填充、显示字符串等功能 + * 适用平台:STM32F103C8T6 + SPI2 + * 作者:王建锋 + * 创建日期:2026-07-13 + * 修改记录: + * 2026-07-13 王建锋 创建初始版本 + */ + +#ifndef __ST7735S_H +#define __ST7735S_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "main.h" +#include + +/* 屏幕参数 */ +#define LCD_WIDTH 128 /* 屏幕宽度 */ +#define LCD_HEIGHT 160 /* 屏幕高度 */ + +/* 颜色定义 (RGB565) */ +#define COLOR_BLACK 0x0000 +#define COLOR_WHITE 0xFFFF +#define COLOR_RED 0xF800 +#define COLOR_GREEN 0x07E0 +#define COLOR_BLUE 0x001F +#define COLOR_YELLOW 0xFFE0 +#define COLOR_CYAN 0x07FF +#define COLOR_MAGENTA 0xF81F +#define COLOR_ORANGE 0xFD20 +#define COLOR_DARK_BLUE 0x0010 +#define COLOR_DARK_GREEN 0x0200 +#define COLOR_DARK_RED 0x8000 + +/* 颜色转换宏 */ +#define RGB565(r, g, b) ((uint16_t)(((r) & 0xF8) << 8 | ((g) & 0xFC) << 3 | ((b) >> 3))) + +/* LCD控制引脚定义 - 根据CubeMX配置修改 */ +#define LCD_CS_PORT LCD_CS_GPIO_Port +#define LCD_CS_PIN LCD_CS_Pin +#define LCD_DC_PORT LCD_DC_GPIO_Port +#define LCD_DC_PIN LCD_DC_Pin +#define LCD_RST_PORT LCD_RST_GPIO_Port +#define LCD_RST_PIN LCD_RST_Pin +#define LCD_SCL_PORT GPIOB +#define LCD_SCL_PIN GPIO_PIN_13 +#define LCD_SDA_PORT GPIOB +#define LCD_SDA_PIN GPIO_PIN_15 + +/* LCD命令定义 */ +#define LCD_CMD_SWRESET 0x01 /* 软件复位 */ +#define LCD_CMD_SLPOUT 0x11 /* 退出睡眠 */ +#define LCD_CMD_DISPON 0x29 /* 显示开启 */ +#define LCD_CMD_DISPOFF 0x28 /* 显示关闭 */ +#define LCD_CMD_CASET 0x2A /* 列地址设置 */ +#define LCD_CMD_RASET 0x2B /* 行地址设置 */ +#define LCD_CMD_RAMWR 0x2C /* 写入显存 */ +#define LCD_CMD_MADCTL 0x36 /* 存储器访问控制 */ +#define LCD_CMD_COLMOD 0x3A /* 像素格式设置 */ +#define LCD_CMD_FRMCTR1 0xB1 /* 帧率控制1 */ +#define LCD_CMD_FRMCTR2 0xB2 /* 帧率控制2 */ +#define LCD_CMD_FRMCTR3 0xB3 /* 帧率控制3 */ +#define LCD_CMD_INVCTR 0xB4 /* 显示反转控制 */ +#define LCD_CMD_PWCTR1 0xC0 /* 功率控制1 */ +#define LCD_CMD_PWCTR2 0xC1 /* 功率控制2 */ +#define LCD_CMD_PWCTR3 0xC2 /* 功率控制3 */ +#define LCD_CMD_PWCTR4 0xC3 /* 功率控制4 */ +#define LCD_CMD_PWCTR5 0xC4 /* 功率控制5 */ +#define LCD_CMD_VMCTR1 0xC5 /* VCOM控制1 */ +#define LCD_CMD_GMCTRP1 0xE0 /* Gamma正向校正 */ +#define LCD_CMD_GMCTRN1 0xE1 /* Gamma反向校正 */ + +/* 字体定义 */ +#define FONT_WIDTH_8 8 /* 8x16字体宽度(含间距) */ +#define FONT_HEIGHT_16 16 /* 8x16字体高度 */ + +/* + * 函数功能:LCD初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:初始化ST7735S屏幕,包括SPI、GPIO、显示参数配置 + */ +void st7735s_init(void); + +/* + * 函数功能:设置显示窗口 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * 返回值:无 + * 函数说明:设置后续写入操作的窗口区域 + */ +void st7735s_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + +/* + * 函数功能:填充矩形区域 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * color - 填充颜色 (RGB565) + * 返回值:无 + * 函数说明:用指定颜色填充矩形区域 + */ +void st7735s_fill_rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); + +/* + * 函数功能:全屏填充 + * 入口参数:color - 填充颜色 (RGB565) + * 返回值:无 + * 函数说明:用指定颜色填充整个屏幕 + */ +void st7735s_fill_screen(uint16_t color); + +/* + * 函数功能:画点 + * 入口参数:x - 列坐标 + * y - 行坐标 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置画一个点 + */ +void st7735s_draw_pixel(uint16_t x, uint16_t y, uint16_t color); + +/* + * 函数功能:画线 + * 入口参数:x1 - 起始列 + * y1 - 起始行 + * x2 - 结束列 + * y2 - 结束行 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一条直线(Bresenham算法) + */ +void st7735s_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); + +/* + * 函数功能:画矩形 + * 入口参数:x - 左上角列 + * y - 左上角行 + * width - 宽度 + * height - 高度 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一个空心矩形 + */ +void st7735s_draw_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color); + +/* + * 函数功能:画圆 + * 入口参数:x0 - 圆心列 + * y0 - 圆心行 + * radius - 半径 + * color - 颜色 (RGB565) + * 返回值:无 + * 函数说明:画一个空心圆(Bresenham算法) + */ +void st7735s_draw_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t color); + +/* + * 函数功能:显示字符 + * 入口参数:x - 列坐标 + * y - 行坐标 + * ch - 字符 (ASCII 32-126) + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置显示一个8x16 ASCII字符 + */ +void st7735s_draw_char(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_color); + +/* + * 函数功能:显示字符串 + * 入口参数:x - 列坐标 + * y - 行坐标 + * str - 字符串指针 + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:在指定位置显示字符串 + */ +void st7735s_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color); + +/* + * 函数功能:设置屏幕方向 + * 入口参数:rotation - 方向 (0-3) + * 返回值:无 + * 函数说明:设置屏幕显示方向 + * 0: 竖屏 + * 1: 横屏 + * 2: 竖屏反转 + * 3: 横屏反转 + */ +void st7735s_set_rotation(uint8_t rotation); + +/* + * 函数功能:设置背光 + * 入口参数:state - 1:开 0:关 + * 返回值:无 + * 函数说明:控制LCD背光(如有硬件背光控制) + */ +void st7735s_backlight(uint8_t state); + +#ifdef __cplusplus +} +#endif + +#endif /* __ST7735S_H */ diff --git a/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.c b/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.c new file mode 100644 index 0000000..9e8eded --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.c @@ -0,0 +1,192 @@ +/* + * 模块名称:按键驱动适配层 + * 模块功能:提供MultiButton库与STM32 HAL库的适配接口 + * 适用平台:STM32F103C8T6 + * 作者:王建锋 + * 创建日期:2026-07-13 + * 修改记录: + * 2026-07-13 王建锋 创建初始版本 + */ + +#include "button_driver.h" +#include "main.h" +#include + +/* 按键句柄数组 */ +static Button s_button_handles[BUTTON_ID_MAX]; + +/* 按键GPIO端口和引脚映射表 */ +typedef struct { + GPIO_TypeDef* port; /* GPIO端口 */ + uint16_t pin; /* GPIO引脚 */ +} ButtonGpio_t; + +static const ButtonGpio_t s_button_gpio[BUTTON_ID_MAX] = { + {KEY1_GPIO_Port, KEY1_Pin}, /* KEY1: PB4 左上*/ + {KEY2_GPIO_Port, KEY2_Pin}, /* KEY2: PB5 右上*/ + {KEY3_GPIO_Port, KEY3_Pin}, /* KEY3: PB3 右下*/ + {KEY4_GPIO_Port, KEY4_Pin}, /* KEY4: PC14 左下*/ + {KEY5_GPIO_Port, KEY5_Pin}, /* KEY5: PC15 中间*/ +}; + +/* + * 函数功能:获取指定按键的电平状态 + * 入口参数:button_id - 按键标识符 + * 返回值:GPIO电平值 (0或1) + * 函数说明:根据按键ID读取对应GPIO引脚的电平 + */ +uint8_t button_driver_read_level(uint8_t button_id) +{ + if (button_id >= BUTTON_ID_MAX) { + return 0; + } + return HAL_GPIO_ReadPin(s_button_gpio[button_id].port, s_button_gpio[button_id].pin); +} + +/* + * 函数功能:KEY1按键回调函数 + * 入口参数:handle - 按键句柄 + * user_data - 用户数据指针 + * 返回值:无 + * 函数说明:KEY1按下时翻转LED + */ +static void button_key1_callback(Button* handle, void* user_data) +{ + (void)handle; + (void)user_data; + printf("KEY1\n"); +} + +/* + * 函数功能:KEY2单击回调函数 + * 入口参数:handle - 按键句柄 + * user_data - 用户数据指针 + * 返回值:无 + * 函数说明:KEY2单击时点亮LED + */ +static void button_key2_single_click(Button* handle, void* user_data) +{ + (void)handle; + (void)user_data; + printf("KEY2\n"); +} + +/* + * 函数功能:KEY3单击回调函数 + * 入口参数:handle - 按键句柄 + * user_data - 用户数据指针 + * 返回值:无 + * 函数说明:KEY3单击事件处理 + */ +static void button_key3_single_click(Button* handle, void* user_data) +{ + (void)handle; + (void)user_data; + printf("KEY3: \n"); +} + +/* + * 函数功能:KEY4单击回调函数 + * 入口参数:handle - 按键句柄 + * user_data - 用户数据指针 + * 返回值:无 + * 函数说明:KEY4单击事件处理 + */ +static void button_key4_single_click(Button* handle, void* user_data) +{ + (void)handle; + (void)user_data; + printf("KEY4\n"); +} + +/* + * 函数功能:KEY5单击回调函数 + * 入口参数:handle - 按键句柄 + * user_data - 用户数据指针 + * 返回值:无 + * 函数说明:KEY5单击事件处理 + */ +static void button_key5_single_click(Button* handle, void* user_data) +{ + (void)handle; + (void)user_data; + printf("KEY5\n"); +} + +/* + * 函数功能:按键驱动初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:初始化所有按键对象,注册回调函数,启动按键轮询 + */ +void button_driver_init(void) +{ + /* 初始化KEY1 */ + button_init(&s_button_handles[BUTTON_ID_KEY1], + button_driver_read_level, + BUTTON_ACTIVE_LEVEL_LOW, + BUTTON_ID_KEY1); + button_attach(&s_button_handles[BUTTON_ID_KEY1], + BTN_SINGLE_CLICK, + button_key1_callback, + NULL); + button_start(&s_button_handles[BUTTON_ID_KEY1]); + + /* 初始化KEY2 */ + button_init(&s_button_handles[BUTTON_ID_KEY2], + button_driver_read_level, + BUTTON_ACTIVE_LEVEL_LOW, + BUTTON_ID_KEY2); + button_attach(&s_button_handles[BUTTON_ID_KEY2], + BTN_SINGLE_CLICK, + button_key2_single_click, + NULL); + button_start(&s_button_handles[BUTTON_ID_KEY2]); + + /* 初始化KEY3 */ + button_init(&s_button_handles[BUTTON_ID_KEY3], + button_driver_read_level, + BUTTON_ACTIVE_LEVEL_LOW, + BUTTON_ID_KEY3); + button_attach(&s_button_handles[BUTTON_ID_KEY3], + BTN_SINGLE_CLICK, + button_key3_single_click, + NULL); + button_start(&s_button_handles[BUTTON_ID_KEY3]); + + /* 初始化KEY4 */ + button_init(&s_button_handles[BUTTON_ID_KEY4], + button_driver_read_level, + BUTTON_ACTIVE_LEVEL_LOW, + BUTTON_ID_KEY4); + button_attach(&s_button_handles[BUTTON_ID_KEY4], + BTN_SINGLE_CLICK, + button_key4_single_click, + NULL); + button_start(&s_button_handles[BUTTON_ID_KEY4]); + + /* 初始化KEY5 */ + button_init(&s_button_handles[BUTTON_ID_KEY5], + button_driver_read_level, + BUTTON_ACTIVE_LEVEL_LOW, + BUTTON_ID_KEY5); + button_attach(&s_button_handles[BUTTON_ID_KEY5], + BTN_SINGLE_CLICK, + button_key5_single_click, + NULL); + button_start(&s_button_handles[BUTTON_ID_KEY5]); +} + +/* + * 函数功能:获取指定按键的事件 + * 入口参数:button_id - 按键标识符 + * 返回值:按键事件 + * 函数说明:返回指定按键的当前事件 + */ +ButtonEvent button_driver_get_event(uint8_t button_id) +{ + if (button_id >= BUTTON_ID_MAX) { + return BTN_NONE_PRESS; + } + return button_get_event(&s_button_handles[button_id]); +} diff --git a/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.h b/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.h new file mode 100644 index 0000000..d6dd2c4 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.h @@ -0,0 +1,63 @@ +/* + * 模块名称:按键驱动适配层 + * 模块功能:提供MultiButton库与STM32 HAL库的适配接口 + * 适用平台:STM32F103C8T6 + * 作者:王建锋 + * 创建日期:2026-07-13 + * 修改记录: + * 2026-07-13 王建锋 创建初始版本 + */ + +#ifndef __BUTTON_DRIVER_H +#define __BUTTON_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "multi_button.h" +#include "main.h" + +/* 按键ID定义 */ +typedef enum { + BUTTON_ID_KEY1 = 0, /* KEY1: PB4 */ + BUTTON_ID_KEY2, /* KEY2: PB5 */ + BUTTON_ID_KEY3, /* KEY3: PB3 */ + BUTTON_ID_KEY4, /* KEY4: PC14 */ + BUTTON_ID_KEY5, /* KEY5: PC15 */ + BUTTON_ID_MAX /* 按键总数 */ +} ButtonId_t; + +/* 按键有效电平定义 */ +#define BUTTON_ACTIVE_LEVEL_LOW 0 /* 低电平有效 */ +#define BUTTON_ACTIVE_LEVEL_HIGH 1 /* 高电平有效 */ + +/* + * 函数功能:按键驱动初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:初始化所有按键对象,注册回调函数,启动按键轮询 + */ +void button_driver_init(void); + +/* + * 函数功能:获取指定按键的电平状态 + * 入口参数:button_id - 按键标识符 + * 返回值:GPIO电平值 (0或1) + * 函数说明:根据按键ID读取对应GPIO引脚的电平 + */ +uint8_t button_driver_read_level(uint8_t button_id); + +/* + * 函数功能:获取指定按键的事件 + * 入口参数:button_id - 按键标识符 + * 返回值:按键事件 + * 函数说明:返回指定按键的当前事件 + */ +ButtonEvent button_driver_get_event(uint8_t button_id); + +#ifdef __cplusplus +} +#endif + +#endif /* __BUTTON_DRIVER_H */ diff --git a/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.c b/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.c new file mode 100644 index 0000000..f8e2531 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2016 Zibin Zheng + * All rights reserved. + */ + +#include "multi_button.h" + +/* 回调执行宏,包含空值检查,传递user_data */ +#define EVENT_CB(ev) do { if (handle->cb[ev]) handle->cb[ev](handle, handle->user_data); } while(0) + +/* 按键句柄链表头 */ +static Button* head_handle = NULL; + +/* 前向声明 */ +static void button_handler(Button* handle); +static inline uint8_t button_read_level(Button* handle); + +/* + * 函数功能:初始化按键结构体句柄 + * 入口参数:handle - 按键句柄结构体指针 + * pin_level - 读取按键GPIO电平的函数指针 + * active_level - 按下时的有效电平 + * button_id - 按键标识符 + * 返回值:无 + * 函数说明:初始化按键状态机和所有参数 + */ +void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id) +{ + if (!handle || !pin_level) { + return; + } + + memset(handle, 0, sizeof(Button)); + handle->event = (uint8_t)BTN_NONE_PRESS; + handle->hal_button_level = pin_level; + handle->button_level = !active_level; + handle->active_level = active_level; + handle->button_id = button_id; + handle->state = BTN_STATE_IDLE; +} + +/* + * 函数功能:绑定按键事件回调函数 + * 入口参数:handle - 按键句柄结构体指针 + * event - 触发事件类型 + * cb - 回调函数 + * user_data - 传递给回调的用户上下文指针 + * 返回值:无 + * 函数说明:为指定事件注册回调函数 + */ +void button_attach(Button* handle, ButtonEvent event, BtnCallback cb, void* user_data) +{ + if (!handle || event >= BTN_EVENT_COUNT) { + return; + } + handle->cb[event] = cb; + handle->user_data = user_data; +} + +/* + * 函数功能:解绑按键事件回调函数 + * 入口参数:handle - 按键句柄结构体指针 + * event - 触发事件类型 + * 返回值:无 + * 函数说明:移除指定事件的回调函数 + */ +void button_detach(Button* handle, ButtonEvent event) +{ + if (!handle || event >= BTN_EVENT_COUNT) { + return; + } + handle->cb[event] = NULL; +} + +/* + * 函数功能:获取按键事件 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:按键事件 + * 函数说明:返回当前发生的按键事件 + */ +ButtonEvent button_get_event(Button* handle) +{ + if (!handle) { + return BTN_NONE_PRESS; + } + return (ButtonEvent)(handle->event); +} + +/* + * 函数功能:获取按键重复按下次数 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:重复按下次数 + * 函数说明:返回连击次数 + */ +uint8_t button_get_repeat_count(Button* handle) +{ + if (!handle) { + return 0; + } + return handle->repeat; +} + +/* + * 函数功能:重置按键状态到空闲 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:无 + * 函数说明:将按键状态机重置为初始状态 + */ +void button_reset(Button* handle) +{ + if (!handle) { + return; + } + handle->state = BTN_STATE_IDLE; + handle->ticks = 0; + handle->repeat = 0; + handle->event = (uint8_t)BTN_NONE_PRESS; + handle->debounce_cnt = 0; +} + +/* + * 函数功能:检查按键是否按下 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:1 - 按下,0 - 未按下,-1 - 错误 + * 函数说明:检查当前按键是否处于按下状态 + */ +int button_is_pressed(Button* handle) +{ + if (!handle) { + return -1; + } + return (handle->button_level == handle->active_level) ? 1 : 0; +} + +/* + * 函数功能:读取按键电平 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:按键电平 + * 函数说明:通过HAL函数读取GPIO电平 + */ +static inline uint8_t button_read_level(Button* handle) +{ + return handle->hal_button_level(handle->button_id); +} + +/* + * 函数功能:按键驱动核心函数,驱动状态机 + * 入口参数:handle - 按键句柄结构体指针 + * 返回值:无 + * 函数说明:实现按键消抖和事件检测的状态机 + */ +static void button_handler(Button* handle) +{ + uint8_t read_gpio_level = button_read_level(handle); + + /* 非空闲状态下增加tick计数器(饱和处理) */ + if (handle->state > BTN_STATE_IDLE) { + if (handle->ticks < UINT16_MAX) { + handle->ticks++; + } + } + + /* 按键消抖处理 */ + if (read_gpio_level != handle->button_level) { + if (++(handle->debounce_cnt) >= DEBOUNCE_TICKS) { + handle->button_level = read_gpio_level; + handle->debounce_cnt = 0; + } + } else { + handle->debounce_cnt = 0; + } + + /* 状态机 */ + switch (handle->state) { + case BTN_STATE_IDLE: + if (handle->button_level == handle->active_level) { + /* 检测到按键按下 */ + handle->event = (uint8_t)BTN_PRESS_DOWN; + EVENT_CB(BTN_PRESS_DOWN); + handle->ticks = 0; + handle->repeat = 1; + handle->state = BTN_STATE_PRESS; + } else { + handle->event = (uint8_t)BTN_NONE_PRESS; + } + break; + + case BTN_STATE_PRESS: + if (handle->button_level != handle->active_level) { + /* 按键释放 */ + handle->event = (uint8_t)BTN_PRESS_UP; + EVENT_CB(BTN_PRESS_UP); + handle->ticks = 0; + handle->state = BTN_STATE_RELEASE; + } else if (handle->ticks > LONG_TICKS) { + /* 检测到长按 */ + handle->event = (uint8_t)BTN_LONG_PRESS_START; + EVENT_CB(BTN_LONG_PRESS_START); + handle->state = BTN_STATE_LONG_HOLD; + } + break; + + case BTN_STATE_RELEASE: + if (handle->button_level == handle->active_level) { + /* 按键再次按下 */ + handle->event = (uint8_t)BTN_PRESS_DOWN; + EVENT_CB(BTN_PRESS_DOWN); + if (handle->repeat < PRESS_REPEAT_MAX_NUM) { + handle->repeat++; + } + handle->event = (uint8_t)BTN_PRESS_REPEAT; + EVENT_CB(BTN_PRESS_REPEAT); + handle->ticks = 0; + handle->state = BTN_STATE_REPEAT; + } else if (handle->ticks > SHORT_TICKS) { + /* 超时,判断点击类型 */ + if (handle->repeat == 1) { + handle->event = (uint8_t)BTN_SINGLE_CLICK; + EVENT_CB(BTN_SINGLE_CLICK); + } else if (handle->repeat == 2) { + handle->event = (uint8_t)BTN_DOUBLE_CLICK; + EVENT_CB(BTN_DOUBLE_CLICK); + } + handle->state = BTN_STATE_IDLE; + } + break; + + case BTN_STATE_REPEAT: + if (handle->button_level != handle->active_level) { + /* 按键释放 */ + handle->event = (uint8_t)BTN_PRESS_UP; + EVENT_CB(BTN_PRESS_UP); + if (handle->ticks < SHORT_TICKS) { + handle->ticks = 0; + handle->state = BTN_STATE_RELEASE; + } else { + handle->state = BTN_STATE_IDLE; + } + } else if (handle->ticks > SHORT_TICKS) { + /* 按住时间过长,视为普通按下 */ + handle->ticks = 0; + handle->repeat = 0; + handle->state = BTN_STATE_PRESS; + } + break; + + case BTN_STATE_LONG_HOLD: + if (handle->button_level == handle->active_level) { + /* 继续保持按下 */ + handle->event = (uint8_t)BTN_LONG_PRESS_HOLD; + EVENT_CB(BTN_LONG_PRESS_HOLD); + } else { + /* 从长按中释放 */ + handle->event = (uint8_t)BTN_PRESS_UP; + EVENT_CB(BTN_PRESS_UP); + handle->state = BTN_STATE_IDLE; + } + break; + + default: + /* 无效状态,重置为空闲 */ + handle->state = BTN_STATE_IDLE; + break; + } +} + +/* + * 函数功能:启动按键工作,将句柄添加到工作链表 + * 入口参数:handle - 目标句柄结构体指针 + * 返回值:0 - 成功,-1 - 已存在,-2 - 无效参数 + * 函数说明:将按键添加到轮询链表中 + */ +int button_start(Button* handle) +{ + if (!handle) { + return -2; + } + + Button* target = head_handle; + while (target) { + if (target == handle) { + return -1; + } + target = target->next; + } + + handle->next = head_handle; + head_handle = handle; + return 0; +} + +/* + * 函数功能:停止按键工作,从工作链表移除句柄 + * 入口参数:handle - 目标句柄结构体指针 + * 返回值:无 + * 函数说明:将按键从轮询链表中移除 + */ +void button_stop(Button* handle) +{ + if (!handle) { + return; + } + + Button** curr; + for (curr = &head_handle; *curr; ) { + Button* entry = *curr; + if (entry == handle) { + *curr = entry->next; + entry->next = NULL; + return; + } else { + curr = &entry->next; + } + } +} + +/* + * 函数功能:后台tick处理,定时器重复调用,间隔5ms + * 入口参数:无 + * 返回值:无 + * 函数说明:遍历链表调用每个按键的状态机处理函数 + */ +void button_ticks(void) +{ + Button* target; + Button* next; + + target = head_handle; + while (target) { + next = target->next; + button_handler(target); + target = next; + } +} diff --git a/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.h b/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.h new file mode 100644 index 0000000..05377a5 --- /dev/null +++ b/STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 Zibin Zheng + * All rights reserved. + */ + +#ifndef MULTI_BUTTON_H +#define MULTI_BUTTON_H + +#include +#include + +/* 版本信息 */ +#define MULTIBUTTON_VERSION_MAJOR 1 +#define MULTIBUTTON_VERSION_MINOR 1 +#define MULTIBUTTON_VERSION_PATCH 1 + +/* 配置常量 - 可根据需求修改 */ +#define TICKS_INTERVAL 5 /* 定时器轮询间隔,单位:毫秒 */ +#define DEBOUNCE_TICKS 3 /* 消抖滤波深度,最大7 (0~7) */ +#define SHORT_TICKS (300 / TICKS_INTERVAL) /* 短按阈值 */ +#define LONG_TICKS (1000 / TICKS_INTERVAL) /* 长按阈值 */ +#define PRESS_REPEAT_MAX_NUM 15 /* 最大重复计数器值 */ + +/* 编译时检查:debounce_cnt 是3位域,最大值为7 */ +#if DEBOUNCE_TICKS > 7 + #error "DEBOUNCE_TICKS exceeds 3-bit field maximum (7)" +#endif + +/* 前向声明 */ +typedef struct _Button Button; + +/* 按键回调函数类型 */ +typedef void (*BtnCallback)(Button* handle, void* user_data); + +/* 按键事件类型 */ +typedef enum { + BTN_PRESS_DOWN = 0, /* 按键按下 */ + BTN_PRESS_UP, /* 按键释放 */ + BTN_PRESS_REPEAT, /* 重复按下检测 */ + BTN_SINGLE_CLICK, /* 单击完成 */ + BTN_DOUBLE_CLICK, /* 双击完成 */ + BTN_LONG_PRESS_START, /* 长按开始 */ + BTN_LONG_PRESS_HOLD, /* 长按保持 */ + BTN_EVENT_COUNT, /* 事件总数 */ + BTN_NONE_PRESS /* 无事件 */ +} ButtonEvent; + +/* 按键状态机状态 */ +typedef enum { + BTN_STATE_IDLE = 0, /* 空闲状态 */ + BTN_STATE_PRESS, /* 按下状态 */ + BTN_STATE_RELEASE, /* 释放后等待超时 */ + BTN_STATE_REPEAT, /* 重复按下状态 */ + BTN_STATE_LONG_HOLD /* 长按保持状态 */ +} ButtonState; + +/* 按键结构体 */ +struct _Button { + uint16_t ticks; /* tick计数器 */ + uint8_t repeat : 4; /* 重复计数器 (0-15) */ + uint8_t event : 4; /* 当前事件 (0-15) */ + uint8_t state : 3; /* 状态机状态 (0-7) */ + uint8_t debounce_cnt : 3; /* 消抖计数器 (0-7) */ + uint8_t active_level : 1; /* 有效GPIO电平 (0或1) */ + uint8_t button_level : 1; /* 当前按键电平 */ + uint8_t button_id; /* 按键标识符 */ + uint8_t (*hal_button_level)(uint8_t button_id); /* HAL读取GPIO函数 */ + BtnCallback cb[BTN_EVENT_COUNT]; /* 回调函数数组 */ + void* user_data; /* 传递给回调的用户上下文指针 */ + Button* next; /* 链表中的下一个按键 */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* 公共API函数 */ +void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id); +void button_attach(Button* handle, ButtonEvent event, BtnCallback cb, void* user_data); +void button_detach(Button* handle, ButtonEvent event); +ButtonEvent button_get_event(Button* handle); +int button_start(Button* handle); +void button_stop(Button* handle); +void button_ticks(void); + +/* 工具函数 */ +uint8_t button_get_repeat_count(Button* handle); +void button_reset(Button* handle); +int button_is_pressed(Button* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* MULTI_BUTTON_H */ diff --git a/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h new file mode 100644 index 0000000..309eb5b --- /dev/null +++ b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h @@ -0,0 +1,734 @@ +/** + ****************************************************************************** + * @file stm32f1xx_hal_spi.h + * @author MCD Application Team + * @brief Header file of SPI HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32F1xx_HAL_SPI_H +#define STM32F1xx_HAL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal_def.h" + +/** @addtogroup STM32F1xx_HAL_Driver + * @{ + */ + +/** @addtogroup SPI + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SPI_Exported_Types SPI Exported Types + * @{ + */ + +/** + * @brief SPI Configuration Structure definition + */ +typedef struct +{ + uint32_t Mode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_Mode */ + + uint32_t Direction; /*!< Specifies the SPI bidirectional mode state. + This parameter can be a value of @ref SPI_Direction */ + + uint32_t DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_Data_Size */ + + uint32_t CLKPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint32_t CLKPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint32_t BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint32_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint32_t TIMode; /*!< Specifies if the TI mode is enabled or not. + This parameter can be a value of @ref SPI_TI_mode */ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_CRC_Calculation */ + + uint32_t CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be an odd number between Min_Data = 1 and Max_Data = 65535 */ +} SPI_InitTypeDef; + +/** + * @brief HAL SPI State structure definition + */ +typedef enum +{ + HAL_SPI_STATE_RESET = 0x00U, /*!< Peripheral not Initialized */ + HAL_SPI_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_SPI_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ + HAL_SPI_STATE_BUSY_TX = 0x03U, /*!< Data Transmission process is ongoing */ + HAL_SPI_STATE_BUSY_RX = 0x04U, /*!< Data Reception process is ongoing */ + HAL_SPI_STATE_BUSY_TX_RX = 0x05U, /*!< Data Transmission and Reception process is ongoing */ + HAL_SPI_STATE_ERROR = 0x06U, /*!< SPI error state */ + HAL_SPI_STATE_ABORT = 0x07U /*!< SPI abort is ongoing */ +} HAL_SPI_StateTypeDef; + +/** + * @brief SPI handle Structure definition + */ +typedef struct __SPI_HandleTypeDef +{ + SPI_TypeDef *Instance; /*!< SPI registers base address */ + + SPI_InitTypeDef Init; /*!< SPI communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to SPI Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< SPI Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< SPI Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to SPI Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< SPI Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< SPI Rx Transfer Counter */ + + void (*RxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Rx ISR */ + + void (*TxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Tx ISR */ + + DMA_HandleTypeDef *hdmatx; /*!< SPI Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< SPI Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_SPI_StateTypeDef State; /*!< SPI communication state */ + + __IO uint32_t ErrorCode; /*!< SPI Error code */ + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Completed callback */ + void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Completed callback */ + void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Completed callback */ + void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Half Completed callback */ + void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Half Completed callback */ + void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Half Completed callback */ + void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Error callback */ + void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Abort callback */ + void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp Init callback */ + void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp DeInit callback */ + +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} SPI_HandleTypeDef; + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +/** + * @brief HAL SPI Callback ID enumeration definition + */ +typedef enum +{ + HAL_SPI_TX_COMPLETE_CB_ID = 0x00U, /*!< SPI Tx Completed callback ID */ + HAL_SPI_RX_COMPLETE_CB_ID = 0x01U, /*!< SPI Rx Completed callback ID */ + HAL_SPI_TX_RX_COMPLETE_CB_ID = 0x02U, /*!< SPI TxRx Completed callback ID */ + HAL_SPI_TX_HALF_COMPLETE_CB_ID = 0x03U, /*!< SPI Tx Half Completed callback ID */ + HAL_SPI_RX_HALF_COMPLETE_CB_ID = 0x04U, /*!< SPI Rx Half Completed callback ID */ + HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID = 0x05U, /*!< SPI TxRx Half Completed callback ID */ + HAL_SPI_ERROR_CB_ID = 0x06U, /*!< SPI Error callback ID */ + HAL_SPI_ABORT_CB_ID = 0x07U, /*!< SPI Abort callback ID */ + HAL_SPI_MSPINIT_CB_ID = 0x08U, /*!< SPI Msp Init callback ID */ + HAL_SPI_MSPDEINIT_CB_ID = 0x09U /*!< SPI Msp DeInit callback ID */ + +} HAL_SPI_CallbackIDTypeDef; + +/** + * @brief HAL SPI Callback pointer definition + */ +typedef void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi); /*!< pointer to an SPI callback function */ + +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_Error_Code SPI Error Code + * @{ + */ +#define HAL_SPI_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_SPI_ERROR_MODF (0x00000001U) /*!< MODF error */ +#define HAL_SPI_ERROR_CRC (0x00000002U) /*!< CRC error */ +#define HAL_SPI_ERROR_OVR (0x00000004U) /*!< OVR error */ +#define HAL_SPI_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ +#define HAL_SPI_ERROR_FLAG (0x00000020U) /*!< Error on RXNE/TXE/BSY Flag */ +#define HAL_SPI_ERROR_ABORT (0x00000040U) /*!< Error during SPI Abort procedure */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +#define HAL_SPI_ERROR_INVALID_CALLBACK (0x00000080U) /*!< Invalid Callback error */ +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SPI_Mode SPI Mode + * @{ + */ +#define SPI_MODE_SLAVE (0x00000000U) +#define SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) +/** + * @} + */ + +/** @defgroup SPI_Direction SPI Direction Mode + * @{ + */ +#define SPI_DIRECTION_2LINES (0x00000000U) +#define SPI_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY +#define SPI_DIRECTION_1LINE SPI_CR1_BIDIMODE +/** + * @} + */ + +/** @defgroup SPI_Data_Size SPI Data Size + * @{ + */ +#define SPI_DATASIZE_8BIT (0x00000000U) +#define SPI_DATASIZE_16BIT SPI_CR1_DFF +/** + * @} + */ + +/** @defgroup SPI_Clock_Polarity SPI Clock Polarity + * @{ + */ +#define SPI_POLARITY_LOW (0x00000000U) +#define SPI_POLARITY_HIGH SPI_CR1_CPOL +/** + * @} + */ + +/** @defgroup SPI_Clock_Phase SPI Clock Phase + * @{ + */ +#define SPI_PHASE_1EDGE (0x00000000U) +#define SPI_PHASE_2EDGE SPI_CR1_CPHA +/** + * @} + */ + +/** @defgroup SPI_Slave_Select_management SPI Slave Select Management + * @{ + */ +#define SPI_NSS_SOFT SPI_CR1_SSM +#define SPI_NSS_HARD_INPUT (0x00000000U) +#define SPI_NSS_HARD_OUTPUT (SPI_CR2_SSOE << 16U) +/** + * @} + */ + +/** @defgroup SPI_BaudRate_Prescaler SPI BaudRate Prescaler + * @{ + */ +#define SPI_BAUDRATEPRESCALER_2 (0x00000000U) +#define SPI_BAUDRATEPRESCALER_4 (SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_8 (SPI_CR1_BR_1) +#define SPI_BAUDRATEPRESCALER_16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_32 (SPI_CR1_BR_2) +#define SPI_BAUDRATEPRESCALER_64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#define SPI_BAUDRATEPRESCALER_256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +/** + * @} + */ + +/** @defgroup SPI_MSB_LSB_transmission SPI MSB LSB Transmission + * @{ + */ +#define SPI_FIRSTBIT_MSB (0x00000000U) +#define SPI_FIRSTBIT_LSB SPI_CR1_LSBFIRST +/** + * @} + */ + +/** @defgroup SPI_TI_mode SPI TI Mode + * @{ + */ +#define SPI_TIMODE_DISABLE (0x00000000U) +/** + * @} + */ + +/** @defgroup SPI_CRC_Calculation SPI CRC Calculation + * @{ + */ +#define SPI_CRCCALCULATION_DISABLE (0x00000000U) +#define SPI_CRCCALCULATION_ENABLE SPI_CR1_CRCEN +/** + * @} + */ + +/** @defgroup SPI_Interrupt_definition SPI Interrupt Definition + * @{ + */ +#define SPI_IT_TXE SPI_CR2_TXEIE +#define SPI_IT_RXNE SPI_CR2_RXNEIE +#define SPI_IT_ERR SPI_CR2_ERRIE +/** + * @} + */ + +/** @defgroup SPI_Flags_definition SPI Flags Definition + * @{ + */ +#define SPI_FLAG_RXNE SPI_SR_RXNE /* SPI status flag: Rx buffer not empty flag */ +#define SPI_FLAG_TXE SPI_SR_TXE /* SPI status flag: Tx buffer empty flag */ +#define SPI_FLAG_BSY SPI_SR_BSY /* SPI status flag: Busy flag */ +#define SPI_FLAG_CRCERR SPI_SR_CRCERR /* SPI Error flag: CRC error flag */ +#define SPI_FLAG_MODF SPI_SR_MODF /* SPI Error flag: Mode fault flag */ +#define SPI_FLAG_OVR SPI_SR_OVR /* SPI Error flag: Overrun flag */ +#define SPI_FLAG_MASK (SPI_SR_RXNE | SPI_SR_TXE | SPI_SR_BSY\ + | SPI_SR_CRCERR | SPI_SR_MODF | SPI_SR_OVR) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup SPI_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @brief Reset SPI handle state. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) \ + do{ \ + (__HANDLE__)->State = HAL_SPI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPI_STATE_RESET) +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + +/** @brief Enable the specified SPI interrupts. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_SPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) + +/** @brief Disable the specified SPI interrupts. + * @param __HANDLE__ specifies the SPI handle. + * This parameter can be SPIx where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_SPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) + +/** @brief Check whether the specified SPI interrupt source is enabled or not. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the SPI interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_SPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified SPI flag is set or not. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SPI_FLAG_RXNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXE: Transmit buffer empty flag + * @arg SPI_FLAG_CRCERR: CRC error flag + * @arg SPI_FLAG_MODF: Mode fault flag + * @arg SPI_FLAG_OVR: Overrun flag + * @arg SPI_FLAG_BSY: Busy flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the SPI CRCERR pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_CRCERRFLAG(__HANDLE__) ((__HANDLE__)->Instance->SR = (uint16_t)(~SPI_FLAG_CRCERR)) + +/** @brief Clear the SPI MODF pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg_modf = 0x00U; \ + tmpreg_modf = (__HANDLE__)->Instance->SR; \ + CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE); \ + UNUSED(tmpreg_modf); \ + } while(0U) + +/** @brief Clear the SPI OVR pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = (__HANDLE__)->Instance->DR; \ + tmpreg_ovr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_ovr); \ + } while(0U) + +/** @brief Enable the SPI peripheral. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) + +/** @brief Disable the SPI peripheral. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SPI_Private_Constants SPI Private Constants + * @{ + */ +#define SPI_INVALID_CRC_ERROR 0U /* CRC error wrongly detected */ +#define SPI_VALID_CRC_ERROR 1U /* CRC error is true */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPI_Private_Macros SPI Private Macros + * @{ + */ + +/** @brief Set the SPI transmit-only mode. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_1LINE_TX(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) + +/** @brief Set the SPI receive-only mode. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_1LINE_RX(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) + +/** @brief Reset the CRC calculation of the SPI. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_RESET_CRC(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \ + SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \ + } while(0U) + +/** @brief Check whether the specified SPI flag is set or not. + * @param __SR__ copy of SPI SR register. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SPI_FLAG_RXNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXE: Transmit buffer empty flag + * @arg SPI_FLAG_CRCERR: CRC error flag + * @arg SPI_FLAG_MODF: Mode fault flag + * @arg SPI_FLAG_OVR: Overrun flag + * @arg SPI_FLAG_BSY: Busy flag + * @retval SET or RESET. + */ +#define SPI_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__) & ((__FLAG__) & SPI_FLAG_MASK)) == \ + ((__FLAG__) & SPI_FLAG_MASK)) ? SET : RESET) + +/** @brief Check whether the specified SPI Interrupt is set or not. + * @param __CR2__ copy of SPI CR2 register. + * @param __INTERRUPT__ specifies the SPI interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval SET or RESET. + */ +#define SPI_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__) & (__INTERRUPT__)) == \ + (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks if SPI Mode parameter is in allowed range. + * @param __MODE__ specifies the SPI Mode. + * This parameter can be a value of @ref SPI_Mode + * @retval None + */ +#define IS_SPI_MODE(__MODE__) (((__MODE__) == SPI_MODE_SLAVE) || \ + ((__MODE__) == SPI_MODE_MASTER)) + +/** @brief Checks if SPI Direction Mode parameter is in allowed range. + * @param __MODE__ specifies the SPI Direction Mode. + * This parameter can be a value of @ref SPI_Direction + * @retval None + */ +#define IS_SPI_DIRECTION(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ + ((__MODE__) == SPI_DIRECTION_2LINES_RXONLY) || \ + ((__MODE__) == SPI_DIRECTION_1LINE)) + +/** @brief Checks if SPI Direction Mode parameter is 2 lines. + * @param __MODE__ specifies the SPI Direction Mode. + * @retval None + */ +#define IS_SPI_DIRECTION_2LINES(__MODE__) ((__MODE__) == SPI_DIRECTION_2LINES) + +/** @brief Checks if SPI Direction Mode parameter is 1 or 2 lines. + * @param __MODE__ specifies the SPI Direction Mode. + * @retval None + */ +#define IS_SPI_DIRECTION_2LINES_OR_1LINE(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ + ((__MODE__) == SPI_DIRECTION_1LINE)) + +/** @brief Checks if SPI Data Size parameter is in allowed range. + * @param __DATASIZE__ specifies the SPI Data Size. + * This parameter can be a value of @ref SPI_Data_Size + * @retval None + */ +#define IS_SPI_DATASIZE(__DATASIZE__) (((__DATASIZE__) == SPI_DATASIZE_16BIT) || \ + ((__DATASIZE__) == SPI_DATASIZE_8BIT)) + +/** @brief Checks if SPI Serial clock steady state parameter is in allowed range. + * @param __CPOL__ specifies the SPI serial clock steady state. + * This parameter can be a value of @ref SPI_Clock_Polarity + * @retval None + */ +#define IS_SPI_CPOL(__CPOL__) (((__CPOL__) == SPI_POLARITY_LOW) || \ + ((__CPOL__) == SPI_POLARITY_HIGH)) + +/** @brief Checks if SPI Clock Phase parameter is in allowed range. + * @param __CPHA__ specifies the SPI Clock Phase. + * This parameter can be a value of @ref SPI_Clock_Phase + * @retval None + */ +#define IS_SPI_CPHA(__CPHA__) (((__CPHA__) == SPI_PHASE_1EDGE) || \ + ((__CPHA__) == SPI_PHASE_2EDGE)) + +/** @brief Checks if SPI Slave Select parameter is in allowed range. + * @param __NSS__ specifies the SPI Slave Select management parameter. + * This parameter can be a value of @ref SPI_Slave_Select_management + * @retval None + */ +#define IS_SPI_NSS(__NSS__) (((__NSS__) == SPI_NSS_SOFT) || \ + ((__NSS__) == SPI_NSS_HARD_INPUT) || \ + ((__NSS__) == SPI_NSS_HARD_OUTPUT)) + +/** @brief Checks if SPI Baudrate prescaler parameter is in allowed range. + * @param __PRESCALER__ specifies the SPI Baudrate prescaler. + * This parameter can be a value of @ref SPI_BaudRate_Prescaler + * @retval None + */ +#define IS_SPI_BAUDRATE_PRESCALER(__PRESCALER__) (((__PRESCALER__) == SPI_BAUDRATEPRESCALER_2) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_4) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_8) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_16) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_32) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_64) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_128) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_256)) + +/** @brief Checks if SPI MSB LSB transmission parameter is in allowed range. + * @param __BIT__ specifies the SPI MSB LSB transmission (whether data transfer starts from MSB or LSB bit). + * This parameter can be a value of @ref SPI_MSB_LSB_transmission + * @retval None + */ +#define IS_SPI_FIRST_BIT(__BIT__) (((__BIT__) == SPI_FIRSTBIT_MSB) || \ + ((__BIT__) == SPI_FIRSTBIT_LSB)) + +/** @brief Checks if SPI TI mode parameter is disabled. + * @param __MODE__ SPI_TIMODE_DISABLE. Device not support Ti Mode. + * This parameter can be a value of @ref SPI_TI_mode + * @retval None + */ +#define IS_SPI_TIMODE(__MODE__) ((__MODE__) == SPI_TIMODE_DISABLE) + +/** @brief Checks if SPI CRC calculation enabled state is in allowed range. + * @param __CALCULATION__ specifies the SPI CRC calculation enable state. + * This parameter can be a value of @ref SPI_CRC_Calculation + * @retval None + */ +#define IS_SPI_CRC_CALCULATION(__CALCULATION__) (((__CALCULATION__) == SPI_CRCCALCULATION_DISABLE) || \ + ((__CALCULATION__) == SPI_CRCCALCULATION_ENABLE)) + +/** @brief Checks if SPI polynomial value to be used for the CRC calculation, is in allowed range. + * @param __POLYNOMIAL__ specifies the SPI polynomial value to be used for the CRC calculation. + * This parameter must be a number between Min_Data = 0 and Max_Data = 65535 + * @retval None + */ +#define IS_SPI_CRC_POLYNOMIAL(__POLYNOMIAL__) (((__POLYNOMIAL__) >= 0x1U) && \ + ((__POLYNOMIAL__) <= 0xFFFFU) && \ + (((__POLYNOMIAL__)&0x1U) != 0U)) + +/** @brief Checks if DMA handle is valid. + * @param __HANDLE__ specifies a DMA Handle. + * @retval None + */ +#define IS_SPI_DMA_HANDLE(__HANDLE__) ((__HANDLE__) != NULL) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SPI_Private_Functions SPI Private Functions + * @{ + */ +uint8_t SPI_ISCRCErrorValid(SPI_HandleTypeDef *hspi); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPI_Exported_Functions + * @{ + */ + +/** @addtogroup SPI_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi); +void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi); +void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, + pSPI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ***************************************************/ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi); + +void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi); +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State and Error functions ***************************************/ +HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi); +uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F1xx_HAL_SPI_H */ + diff --git a/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_spi.h b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_spi.h new file mode 100644 index 0000000..15bfc9a --- /dev/null +++ b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_spi.h @@ -0,0 +1,1951 @@ +/** + ****************************************************************************** + * @file stm32f1xx_ll_spi.h + * @author MCD Application Team + * @brief Header file of SPI LL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32F1xx_LL_SPI_H +#define STM32F1xx_LL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx.h" + +/** @addtogroup STM32F1xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @defgroup SPI_LL SPI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure + * @{ + */ + +/** + * @brief SPI Init structures definition + */ +typedef struct +{ + uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetTransferDirection().*/ + + uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). + This parameter can be a value of @ref SPI_LL_EC_MODE. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetMode().*/ + + uint32_t DataWidth; /*!< Specifies the SPI data width. + This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetDataWidth().*/ + + uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_LL_EC_POLARITY. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetClockPolarity().*/ + + uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_LL_EC_PHASE. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetClockPhase().*/ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) + or by software using the SSI bit. + This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetNSSMode().*/ + + uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used + to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. + @note The communication clock is derived from the master clock. + The slave clock does not need to be set. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetBaudRatePrescaler().*/ + + uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetTransferBitOrder().*/ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. + + This feature can be modified afterwards using unitary + functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ + + uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary + function @ref LL_SPI_SetCRCPolynomial().*/ + +} LL_SPI_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_SPI_ReadReg function + * @{ + */ +#define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ +#define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ +#define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ +#define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ +#define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ +#define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ +/** + * @} + */ + + +/** @defgroup SPI_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ +#define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ +#define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler + * @{ + */ +#define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order + * @{ + */ +#define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ +#define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode + * @{ + */ +#define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ +#define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ +#define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ +#define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode + * @{ + */ +#define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ +#define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ +#define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_SPI_DATAWIDTH_8BIT 0x00000000U /*!< Data length for SPI transfer: 8 bits */ +#define LL_SPI_DATAWIDTH_16BIT (SPI_CR1_DFF) /*!< Data length for SPI transfer: 16 bits */ +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation + * @{ + */ +#define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ +#define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable SPI peripheral + * @rmtoll CR1 SPE LL_SPI_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Disable SPI peripheral + * @note When disabling the SPI, follow the procedure described in the Reference Manual. + * @rmtoll CR1 SPE LL_SPI_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Check if SPI peripheral is enabled + * @rmtoll CR1 SPE LL_SPI_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabled(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); +} + +/** + * @brief Set SPI operation mode to Master or Slave + * @note This bit should not be changed when communication is ongoing. + * @rmtoll CR1 MSTR LL_SPI_SetMode\n + * CR1 SSI LL_SPI_SetMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); +} + +/** + * @brief Get SPI operation mode (Master or Slave) + * @rmtoll CR1 MSTR LL_SPI_GetMode\n + * CR1 SSI LL_SPI_GetMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + */ +__STATIC_INLINE uint32_t LL_SPI_GetMode(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); +} + + +/** + * @brief Set clock phase + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPHA LL_SPI_SetClockPhase + * @param SPIx SPI Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); +} + +/** + * @brief Get clock phase + * @rmtoll CR1 CPHA LL_SPI_GetClockPhase + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); +} + +/** + * @brief Set clock polarity + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); +} + +/** + * @brief Get clock polarity + * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); +} + +/** + * @brief Set baud rate prescaler + * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. + * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler + * @param SPIx SPI Instance + * @param BaudRate This parameter can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); +} + +/** + * @brief Get baud rate prescaler + * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + */ +__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); +} + +/** + * @brief Set transfer bit order + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder + * @param SPIx SPI Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); +} + +/** + * @brief Get transfer bit order + * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); +} + +/** + * @brief Set transfer direction mode + * @note For Half-Duplex mode, Rx Direction is set by default. + * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. + * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n + * CR1 BIDIMODE LL_SPI_SetTransferDirection\n + * CR1 BIDIOE LL_SPI_SetTransferDirection + * @param SPIx SPI Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); +} + +/** + * @brief Get transfer direction mode + * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n + * CR1 BIDIMODE LL_SPI_GetTransferDirection\n + * CR1 BIDIOE LL_SPI_GetTransferDirection + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); +} + +/** + * @brief Set frame data width + * @rmtoll CR1 DFF LL_SPI_SetDataWidth + * @param SPIx SPI Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_DFF, DataWidth); +} + +/** + * @brief Get frame data width + * @rmtoll CR1 DFF LL_SPI_GetDataWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_DFF)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_CRC_Management CRC Management + * @{ + */ + +/** + * @brief Enable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_EnableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Disable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_DisableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Check if CRC is enabled + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set CRCNext to transfer CRC on the line + * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. + * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); +} + +/** + * @brief Set polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial + * @param SPIx SPI Instance + * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) +{ + WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); +} + +/** + * @brief Get polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->CRCPR)); +} + +/** + * @brief Get Rx CRC + * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->RXCRCR)); +} + +/** + * @brief Get Tx CRC + * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->TXCRCR)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management + * @{ + */ + +/** + * @brief Set NSS mode + * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. + * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_SetNSSMode + * @param SPIx SPI Instance + * @param NSS This parameter can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); + MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); +} + +/** + * @brief Get NSS mode + * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_GetNSSMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + */ +__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(const SPI_TypeDef *SPIx) +{ + uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); + uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); + return (Ssm | Ssoe); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Get CRC error flag + * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); +} + +/** + * @brief Get mode fault error flag + * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get busy flag + * @note The BSY flag is cleared under any one of the following conditions: + * -When the SPI is correctly disabled + * -When a fault is detected in Master mode (MODF bit set to 1) + * -In Master mode, when it finishes a data transmission and no new data is ready to be + * sent + * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between + * each data transfer. + * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); +} + + +/** + * @brief Clear CRC error flag + * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); +} + +/** + * @brief Clear mode fault error flag + * @note Clearing this flag is done by a read access to the SPIx_SR + * register followed by a write access to the SPIx_CR1 register + * @rmtoll SR MODF LL_SPI_ClearFlag_MODF + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg_sr; + tmpreg_sr = SPIx->SR; + (void) tmpreg_sr; + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Clear overrun error flag + * @note Clearing this flag is done by a read access to the SPIx_DR + * register followed by a read access to the SPIx_SR register + * @rmtoll SR OVR LL_SPI_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->DR; + (void) tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @brief Clear frame format error flag + * @note Clearing this flag is done by reading SPIx_SR register + * @rmtoll SR FRE LL_SPI_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_IT_Management Interrupt Management + * @{ + */ + +/** + * @brief Enable error interrupt + * @note This bit controls the generation of an interrupt when an error condition + * occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Enable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Enable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Disable error interrupt + * @note This bit controls the generation of an interrupt when an error condition + * occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Disable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Disable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Check if error interrupt is enabled + * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Rx buffer not empty interrupt is enabled + * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DMA_Management DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll DR DR LL_SPI_DMA_GetRegAddr + * @param SPIx SPI Instance + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(const SPI_TypeDef *SPIx) +{ + return (uint32_t) &(SPIx->DR); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DATA_Management DATA Management + * @{ + */ + +/** + * @brief Read 8-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData8 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) +{ + return (*((__IO uint8_t *)&SPIx->DR)); +} + +/** + * @brief Read 16-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) +{ + return (uint16_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Write 8-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData8 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) +{ +#if defined (__GNUC__) + __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); + *spidr = TxData; +#else + *((__IO uint8_t *)&SPIx->DR) = TxData; +#endif /* __GNUC__ */ +} + +/** + * @brief Write 16-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ +#if defined (__GNUC__) + __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); + *spidr = TxData; +#else + SPIx->DR = TxData; +#endif /* __GNUC__ */ +} + +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_SPI_DeInit(const SPI_TypeDef *SPIx); +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ +/** + * @} + */ + +/** + * @} + */ + +#if defined(SPI_I2S_SUPPORT) +/** @defgroup I2S_LL I2S + * @{ + */ + +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2S_LL_ES_INIT I2S Exported Init structure + * @{ + */ + +/** + * @brief I2S Init structure definition + */ + +typedef struct +{ + uint32_t Mode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2S_LL_EC_MODE + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetTransferMode().*/ + + uint32_t Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_STANDARD + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetStandard().*/ + + + uint32_t DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_DATA_FORMAT + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetDataFormat().*/ + + + uint32_t MCLKOutput; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_LL_EC_MCLK_OUTPUT + + This feature can be modified afterwards using unitary functions @ref LL_I2S_EnableMasterClock() or @ref LL_I2S_DisableMasterClock.*/ + + + uint32_t AudioFreq; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_AUDIO_FREQ + + Audio Frequency can be modified afterwards using Reference manual formulas to calculate Prescaler Linear, Parity + and unitary functions @ref LL_I2S_SetPrescalerLinear() and @ref LL_I2S_SetPrescalerParity() to set it.*/ + + + uint32_t ClockPolarity; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_LL_EC_POLARITY + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetClockPolarity().*/ + +} LL_I2S_InitTypeDef; + +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2S_LL_Exported_Constants I2S Exported Constants + * @{ + */ + +/** @defgroup I2S_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_I2S_ReadReg function + * @{ + */ +#define LL_I2S_SR_RXNE LL_SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_I2S_SR_TXE LL_SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_I2S_SR_BSY LL_SPI_SR_BSY /*!< Busy flag */ +#define LL_I2S_SR_UDR SPI_SR_UDR /*!< Underrun flag */ +#define LL_I2S_SR_OVR LL_SPI_SR_OVR /*!< Overrun flag */ +#define LL_I2S_SR_FRE LL_SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_I2S_CR2_RXNEIE LL_SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_I2S_CR2_TXEIE LL_SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_I2S_CR2_ERRIE LL_SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_DATA_FORMAT Data format + * @{ + */ +#define LL_I2S_DATAFORMAT_16B 0x00000000U /*!< Data length 16 bits, Channel length 16bit */ +#define LL_I2S_DATAFORMAT_16B_EXTENDED (SPI_I2SCFGR_CHLEN) /*!< Data length 16 bits, Channel length 32bit */ +#define LL_I2S_DATAFORMAT_24B (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_0) /*!< Data length 24 bits, Channel length 32bit */ +#define LL_I2S_DATAFORMAT_32B (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_1) /*!< Data length 16 bits, Channel length 32bit */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_I2S_POLARITY_LOW 0x00000000U /*!< Clock steady state is low level */ +#define LL_I2S_POLARITY_HIGH (SPI_I2SCFGR_CKPOL) /*!< Clock steady state is high level */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_STANDARD I2s Standard + * @{ + */ +#define LL_I2S_STANDARD_PHILIPS 0x00000000U /*!< I2S standard philips */ +#define LL_I2S_STANDARD_MSB (SPI_I2SCFGR_I2SSTD_0) /*!< MSB justified standard (left justified) */ +#define LL_I2S_STANDARD_LSB (SPI_I2SCFGR_I2SSTD_1) /*!< LSB justified standard (right justified) */ +#define LL_I2S_STANDARD_PCM_SHORT (SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1) /*!< PCM standard, short frame synchronization */ +#define LL_I2S_STANDARD_PCM_LONG (SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1 | SPI_I2SCFGR_PCMSYNC) /*!< PCM standard, long frame synchronization */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_I2S_MODE_SLAVE_TX 0x00000000U /*!< Slave Tx configuration */ +#define LL_I2S_MODE_SLAVE_RX (SPI_I2SCFGR_I2SCFG_0) /*!< Slave Rx configuration */ +#define LL_I2S_MODE_MASTER_TX (SPI_I2SCFGR_I2SCFG_1) /*!< Master Tx configuration */ +#define LL_I2S_MODE_MASTER_RX (SPI_I2SCFGR_I2SCFG_0 | SPI_I2SCFGR_I2SCFG_1) /*!< Master Rx configuration */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_PRESCALER_FACTOR Prescaler Factor + * @{ + */ +#define LL_I2S_PRESCALER_PARITY_EVEN 0x00000000U /*!< Odd factor: Real divider value is = I2SDIV * 2 */ +#define LL_I2S_PRESCALER_PARITY_ODD (SPI_I2SPR_ODD >> 8U) /*!< Odd factor: Real divider value is = (I2SDIV * 2)+1 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup I2S_LL_EC_MCLK_OUTPUT MCLK Output + * @{ + */ +#define LL_I2S_MCLK_OUTPUT_DISABLE 0x00000000U /*!< Master clock output is disabled */ +#define LL_I2S_MCLK_OUTPUT_ENABLE (SPI_I2SPR_MCKOE) /*!< Master clock output is enabled */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_AUDIO_FREQ Audio Frequency + * @{ + */ + +#define LL_I2S_AUDIOFREQ_192K 192000U /*!< Audio Frequency configuration 192000 Hz */ +#define LL_I2S_AUDIOFREQ_96K 96000U /*!< Audio Frequency configuration 96000 Hz */ +#define LL_I2S_AUDIOFREQ_48K 48000U /*!< Audio Frequency configuration 48000 Hz */ +#define LL_I2S_AUDIOFREQ_44K 44100U /*!< Audio Frequency configuration 44100 Hz */ +#define LL_I2S_AUDIOFREQ_32K 32000U /*!< Audio Frequency configuration 32000 Hz */ +#define LL_I2S_AUDIOFREQ_22K 22050U /*!< Audio Frequency configuration 22050 Hz */ +#define LL_I2S_AUDIOFREQ_16K 16000U /*!< Audio Frequency configuration 16000 Hz */ +#define LL_I2S_AUDIOFREQ_11K 11025U /*!< Audio Frequency configuration 11025 Hz */ +#define LL_I2S_AUDIOFREQ_8K 8000U /*!< Audio Frequency configuration 8000 Hz */ +#define LL_I2S_AUDIOFREQ_DEFAULT 2U /*!< Audio Freq not specified. Register I2SDIV = 2 */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup I2S_LL_Exported_Macros I2S Exported Macros + * @{ + */ + +/** @defgroup I2S_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in I2S register + * @param __INSTANCE__ I2S Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_I2S_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in I2S register + * @param __INSTANCE__ I2S Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_I2S_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2S_LL_Exported_Functions I2S Exported Functions + * @{ + */ + +/** @defgroup I2S_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Select I2S mode and Enable I2S peripheral + * @rmtoll I2SCFGR I2SMOD LL_I2S_Enable\n + * I2SCFGR I2SE LL_I2S_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE); +} + +/** + * @brief Disable I2S peripheral + * @rmtoll I2SCFGR I2SE LL_I2S_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE); +} + +/** + * @brief Check if I2S peripheral is enabled + * @rmtoll I2SCFGR I2SE LL_I2S_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabled(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SE) == (SPI_I2SCFGR_I2SE)) ? 1UL : 0UL); +} + +/** + * @brief Set I2S data frame length + * @rmtoll I2SCFGR DATLEN LL_I2S_SetDataFormat\n + * I2SCFGR CHLEN LL_I2S_SetDataFormat + * @param SPIx SPI Instance + * @param DataFormat This parameter can be one of the following values: + * @arg @ref LL_I2S_DATAFORMAT_16B + * @arg @ref LL_I2S_DATAFORMAT_16B_EXTENDED + * @arg @ref LL_I2S_DATAFORMAT_24B + * @arg @ref LL_I2S_DATAFORMAT_32B + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetDataFormat(SPI_TypeDef *SPIx, uint32_t DataFormat) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN, DataFormat); +} + +/** + * @brief Get I2S data frame length + * @rmtoll I2SCFGR DATLEN LL_I2S_GetDataFormat\n + * I2SCFGR CHLEN LL_I2S_GetDataFormat + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_DATAFORMAT_16B + * @arg @ref LL_I2S_DATAFORMAT_16B_EXTENDED + * @arg @ref LL_I2S_DATAFORMAT_24B + * @arg @ref LL_I2S_DATAFORMAT_32B + */ +__STATIC_INLINE uint32_t LL_I2S_GetDataFormat(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)); +} + +/** + * @brief Set I2S clock polarity + * @rmtoll I2SCFGR CKPOL LL_I2S_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_I2S_POLARITY_LOW + * @arg @ref LL_I2S_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + SET_BIT(SPIx->I2SCFGR, ClockPolarity); +} + +/** + * @brief Get I2S clock polarity + * @rmtoll I2SCFGR CKPOL LL_I2S_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_POLARITY_LOW + * @arg @ref LL_I2S_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_I2S_GetClockPolarity(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_CKPOL)); +} + +/** + * @brief Set I2S standard protocol + * @rmtoll I2SCFGR I2SSTD LL_I2S_SetStandard\n + * I2SCFGR PCMSYNC LL_I2S_SetStandard + * @param SPIx SPI Instance + * @param Standard This parameter can be one of the following values: + * @arg @ref LL_I2S_STANDARD_PHILIPS + * @arg @ref LL_I2S_STANDARD_MSB + * @arg @ref LL_I2S_STANDARD_LSB + * @arg @ref LL_I2S_STANDARD_PCM_SHORT + * @arg @ref LL_I2S_STANDARD_PCM_LONG + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC, Standard); +} + +/** + * @brief Get I2S standard protocol + * @rmtoll I2SCFGR I2SSTD LL_I2S_GetStandard\n + * I2SCFGR PCMSYNC LL_I2S_GetStandard + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_STANDARD_PHILIPS + * @arg @ref LL_I2S_STANDARD_MSB + * @arg @ref LL_I2S_STANDARD_LSB + * @arg @ref LL_I2S_STANDARD_PCM_SHORT + * @arg @ref LL_I2S_STANDARD_PCM_LONG + */ +__STATIC_INLINE uint32_t LL_I2S_GetStandard(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC)); +} + +/** + * @brief Set I2S transfer mode + * @rmtoll I2SCFGR I2SCFG LL_I2S_SetTransferMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_I2S_MODE_SLAVE_TX + * @arg @ref LL_I2S_MODE_SLAVE_RX + * @arg @ref LL_I2S_MODE_MASTER_TX + * @arg @ref LL_I2S_MODE_MASTER_RX + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetTransferMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_I2SCFG, Mode); +} + +/** + * @brief Get I2S transfer mode + * @rmtoll I2SCFGR I2SCFG LL_I2S_GetTransferMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_MODE_SLAVE_TX + * @arg @ref LL_I2S_MODE_SLAVE_RX + * @arg @ref LL_I2S_MODE_MASTER_TX + * @arg @ref LL_I2S_MODE_MASTER_RX + */ +__STATIC_INLINE uint32_t LL_I2S_GetTransferMode(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SCFG)); +} + +/** + * @brief Set I2S linear prescaler + * @rmtoll I2SPR I2SDIV LL_I2S_SetPrescalerLinear + * @param SPIx SPI Instance + * @param PrescalerLinear Value between Min_Data=0x02 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetPrescalerLinear(SPI_TypeDef *SPIx, uint8_t PrescalerLinear) +{ + MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_I2SDIV, PrescalerLinear); +} + +/** + * @brief Get I2S linear prescaler + * @rmtoll I2SPR I2SDIV LL_I2S_GetPrescalerLinear + * @param SPIx SPI Instance + * @retval PrescalerLinear Value between Min_Data=0x02 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2S_GetPrescalerLinear(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SPR, SPI_I2SPR_I2SDIV)); +} + +/** + * @brief Set I2S parity prescaler + * @rmtoll I2SPR ODD LL_I2S_SetPrescalerParity + * @param SPIx SPI Instance + * @param PrescalerParity This parameter can be one of the following values: + * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN + * @arg @ref LL_I2S_PRESCALER_PARITY_ODD + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetPrescalerParity(SPI_TypeDef *SPIx, uint32_t PrescalerParity) +{ + MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_ODD, PrescalerParity << 8U); +} + +/** + * @brief Get I2S parity prescaler + * @rmtoll I2SPR ODD LL_I2S_GetPrescalerParity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN + * @arg @ref LL_I2S_PRESCALER_PARITY_ODD + */ +__STATIC_INLINE uint32_t LL_I2S_GetPrescalerParity(const SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SPR, SPI_I2SPR_ODD) >> 8U); +} + +/** + * @brief Enable the master clock output (Pin MCK) + * @rmtoll I2SPR MCKOE LL_I2S_EnableMasterClock + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableMasterClock(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE); +} + +/** + * @brief Disable the master clock output (Pin MCK) + * @rmtoll I2SPR MCKOE LL_I2S_DisableMasterClock + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableMasterClock(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE); +} + +/** + * @brief Check if the master clock output (Pin MCK) is enabled + * @rmtoll I2SPR MCKOE LL_I2S_IsEnabledMasterClock + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledMasterClock(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE) == (SPI_I2SPR_MCKOE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_FLAG FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_I2S_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_RXNE(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_RXNE(SPIx); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_I2S_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_TXE(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_TXE(SPIx); +} + +/** + * @brief Get busy flag + * @rmtoll SR BSY LL_I2S_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_BSY(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_BSY(SPIx); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_I2S_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_OVR(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_OVR(SPIx); +} + +/** + * @brief Get underrun error flag + * @rmtoll SR UDR LL_I2S_IsActiveFlag_UDR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_UDR(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_UDR) == (SPI_SR_UDR)) ? 1UL : 0UL); +} + + +/** + * @brief Get channel side flag. + * @note 0: Channel Left has to be transmitted or has been received\n + * 1: Channel Right has to be transmitted or has been received\n + * It has no significance in PCM mode. + * @rmtoll SR CHSIDE LL_I2S_IsActiveFlag_CHSIDE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_CHSIDE(const SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CHSIDE) == (SPI_SR_CHSIDE)) ? 1UL : 0UL); +} + +/** + * @brief Clear overrun error flag + * @rmtoll SR OVR LL_I2S_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + LL_SPI_ClearFlag_OVR(SPIx); +} + +/** + * @brief Clear underrun error flag + * @rmtoll SR UDR LL_I2S_ClearFlag_UDR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_UDR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void)tmpreg; +} + +/** + * @brief Clear frame format error flag + * @rmtoll SR FRE LL_I2S_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + LL_SPI_ClearFlag_FRE(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_IT Interrupt Management + * @{ + */ + +/** + * @brief Enable error IT + * @note This bit controls the generation of an interrupt when an error condition occurs (OVR, UDR and FRE in I2S mode). + * @rmtoll CR2 ERRIE LL_I2S_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_ERR(SPIx); +} + +/** + * @brief Enable Rx buffer not empty IT + * @rmtoll CR2 RXNEIE LL_I2S_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_RXNE(SPIx); +} + +/** + * @brief Enable Tx buffer empty IT + * @rmtoll CR2 TXEIE LL_I2S_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_TXE(SPIx); +} + +/** + * @brief Disable error IT + * @note This bit controls the generation of an interrupt when an error condition occurs (OVR, UDR and FRE in I2S mode). + * @rmtoll CR2 ERRIE LL_I2S_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_ERR(SPIx); +} + +/** + * @brief Disable Rx buffer not empty IT + * @rmtoll CR2 RXNEIE LL_I2S_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_RXNE(SPIx); +} + +/** + * @brief Disable Tx buffer empty IT + * @rmtoll CR2 TXEIE LL_I2S_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_TXE(SPIx); +} + +/** + * @brief Check if ERR IT is enabled + * @rmtoll CR2 ERRIE LL_I2S_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_ERR(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_ERR(SPIx); +} + +/** + * @brief Check if RXNE IT is enabled + * @rmtoll CR2 RXNEIE LL_I2S_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_RXNE(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_RXNE(SPIx); +} + +/** + * @brief Check if TXE IT is enabled + * @rmtoll CR2 TXEIE LL_I2S_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_TXE(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_TXE(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_DMA DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_I2S_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableDMAReq_RX(SPIx); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_I2S_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableDMAReq_RX(SPIx); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_I2S_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledDMAReq_RX(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledDMAReq_RX(SPIx); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_I2S_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableDMAReq_TX(SPIx); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_I2S_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableDMAReq_TX(SPIx); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_I2S_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledDMAReq_TX(const SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledDMAReq_TX(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_DATA DATA Management + * @{ + */ + +/** + * @brief Read 16-Bits in data register + * @rmtoll DR DR LL_I2S_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x0000 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_I2S_ReceiveData16(SPI_TypeDef *SPIx) +{ + return LL_SPI_ReceiveData16(SPIx); +} + +/** + * @brief Write 16-Bits in data register + * @rmtoll DR DR LL_I2S_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x0000 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_I2S_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ + LL_SPI_TransmitData16(SPIx, TxData); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2S_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_I2S_DeInit(const SPI_TypeDef *SPIx); +ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct); +void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct); +void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* SPI_I2S_SUPPORT */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F1xx_LL_SPI_H */ + diff --git a/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c new file mode 100644 index 0000000..16c9c93 --- /dev/null +++ b/STM32F103C8T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c @@ -0,0 +1,4025 @@ +/** + ****************************************************************************** + * @file stm32f1xx_hal_spi.c + * @author MCD Application Team + * @brief SPI HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Serial Peripheral Interface (SPI) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State functions + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The SPI HAL driver can be used as follows: + + (#) Declare a SPI_HandleTypeDef handle structure, for example: + SPI_HandleTypeDef hspi; + + (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API: + (##) Enable the SPIx interface clock + (##) SPI pins configuration + (+++) Enable the clock for the SPI GPIOs + (+++) Configure these SPI pins as alternate function push-pull + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the SPIx interrupt priority + (+++) Enable the NVIC SPI IRQ handle + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel + (+++) Enable the DMAx clock + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx Stream/Channel + (+++) Associate the initialized hdma_tx(or _rx) handle to the hspi DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx + or Rx Stream/Channel + + (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS + management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure. + + (#) Initialize the SPI registers by calling the HAL_SPI_Init() API: + (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_SPI_MspInit() API. + [..] + Circular mode restriction: + (#) The DMA circular mode cannot be used when the SPI is configured in these modes: + (##) Master 2Lines RxOnly + (##) Master 1Line Rx + (#) The CRC feature is not managed when the DMA circular mode is enabled + (#) When the SPI DMA Pause/Stop features are used, we must use the following APIs + the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks + [..] + Master Receive mode restriction: + (#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or + bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI + does not initiate a new transfer the following procedure has to be respected: + (##) HAL_SPI_DeInit() + (##) HAL_SPI_Init() + [..] + Callback registration: + + (#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback. + + Function HAL_SPI_RegisterCallback() allows to register following callbacks: + (++) TxCpltCallback : SPI Tx Completed callback + (++) RxCpltCallback : SPI Rx Completed callback + (++) TxRxCpltCallback : SPI TxRx Completed callback + (++) TxHalfCpltCallback : SPI Tx Half Completed callback + (++) RxHalfCpltCallback : SPI Rx Half Completed callback + (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback + (++) ErrorCallback : SPI Error callback + (++) AbortCpltCallback : SPI Abort callback + (++) MspInitCallback : SPI Msp Init callback + (++) MspDeInitCallback : SPI Msp DeInit callback + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + + (#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default + weak function. + HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (++) TxCpltCallback : SPI Tx Completed callback + (++) RxCpltCallback : SPI Rx Completed callback + (++) TxRxCpltCallback : SPI TxRx Completed callback + (++) TxHalfCpltCallback : SPI Tx Half Completed callback + (++) RxHalfCpltCallback : SPI Rx Half Completed callback + (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback + (++) ErrorCallback : SPI Error callback + (++) AbortCpltCallback : SPI Abort callback + (++) MspInitCallback : SPI Msp Init callback + (++) MspDeInitCallback : SPI Msp DeInit callback + + [..] + By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + + [..] + Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit() + or HAL_SPI_Init() function. + + [..] + When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + [..] + Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes, + the following table resume the max SPI frequency reached with data size 8bits/16bits, + according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance. + + @endverbatim + + Additional table : + + DataSize = SPI_DATASIZE_8BIT: + +----------------------------------------------------------------------------------------------+ + | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line | + | Process | Transfer mode |---------------------|----------------------|----------------------| + | | | Master | Slave | Master | Slave | Master | Slave | + |==============================================================================================| + | T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | / | Interrupt | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA | + | R |----------------|----------|----------|-----------|----------|-----------|----------| + | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | R | Interrupt | Fpclk/8 | Fpclk/8 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128| + +----------------------------------------------------------------------------------------------+ + + DataSize = SPI_DATASIZE_16BIT: + +----------------------------------------------------------------------------------------------+ + | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line | + | Process | Transfer mode |---------------------|----------------------|----------------------| + | | | Master | Slave | Master | Slave | Master | Slave | + |==============================================================================================| + | T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | / | Interrupt | Fpclk/4 | Fpclk/4 | NA | NA | NA | NA | + | R |----------------|----------|----------|-----------|----------|-----------|----------| + | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/32 | Fpclk/2 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | R | Interrupt | Fpclk/4 | Fpclk/4 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/32 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | T | Interrupt | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/64 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128| + +----------------------------------------------------------------------------------------------+ + @note The max SPI frequency depend on SPI data size (8bits, 16bits), + SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA). + @note + (#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and + HAL_SPI_TransmitReceive_DMA() + (#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA() + (#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA() + + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal.h" + +/** @addtogroup STM32F1xx_HAL_Driver + * @{ + */ + +/** @defgroup SPI SPI + * @brief SPI HAL module driver + * @{ + */ +#ifdef HAL_SPI_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +#if (USE_SPI_CRC != 0U) && defined(SPI_CRC_ERROR_WORKAROUND_FEATURE) +/* CRC WORKAROUND FEATURE: Variable used to determine if device is impacted by implementation + * of workaround related to wrong CRC errors detection on SPI2. Conditions in which this workaround + * has to be applied, are: + * - STM32F101CDE/STM32F103CDE + * - Revision ID : Z + * - SPI2 + * - In receive only mode, with CRC calculation enabled, at the end of the CRC reception, + * the software needs to check the CRCERR flag. If it is found set, read back the SPI_RXCRC: + * + If the value is 0, the complete data transfer is successful. + * + Otherwise, one or more errors have been detected during the data transfer by CPU or DMA. + * If CRCERR is found reset, the complete data transfer is considered successful. + * + * Check RevisionID value for identifying if Device is Rev Z (0x0001) in order to enable workaround for + * CRC errors wrongly detected + */ +/* Pb is that ES_STM32F10xxCDE also identify an issue in Debug registers access while not in Debug mode + * Revision ID information is only available in Debug mode, so Workaround could not be implemented + * to distinguish Rev Z devices (issue present) from more recent version (issue fixed). + * So, in case of Revision Z F101 or F103 devices, below define should be assigned to 1. + */ +#define USE_SPI_CRC_ERROR_WORKAROUND 0U +#endif /* USE_SPI_CRC */ +/** @defgroup SPI_Private_Constants SPI Private Constants + * @{ + */ +#define SPI_DEFAULT_TIMEOUT 100U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup SPI_Private_Functions SPI Private Functions + * @{ + */ +static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAError(DMA_HandleTypeDef *hdma); +static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State, + uint32_t Timeout, uint32_t Tickstart); +static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +#if (USE_SPI_CRC != 0U) +static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi); +#endif /* USE_SPI_CRC */ +static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi); +static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + de-initialize the SPIx peripheral: + + (+) User must implement HAL_SPI_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_SPI_Init() to configure the selected device with + the selected configuration: + (++) Mode + (++) Direction + (++) Data Size + (++) Clock Polarity and Phase + (++) NSS Management + (++) BaudRate Prescaler + (++) FirstBit + (++) TIMode + (++) CRC Calculation + (++) CRC Polynomial if CRC enabled + + (+) Call the function HAL_SPI_DeInit() to restore the default configuration + of the selected SPIx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the SPI according to the specified parameters + * in the SPI_InitTypeDef and initialize the associated handle. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi) +{ + /* Check the SPI handle allocation */ + if (hspi == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance)); + assert_param(IS_SPI_MODE(hspi->Init.Mode)); + assert_param(IS_SPI_DIRECTION(hspi->Init.Direction)); + assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize)); + assert_param(IS_SPI_NSS(hspi->Init.NSS)); + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit)); + /* TI mode is not supported on this device. + TIMode parameter is mandatory equal to SPI_TIMODE_DISABLE */ + assert_param(IS_SPI_TIMODE(hspi->Init.TIMode)); + if (hspi->Init.TIMode == SPI_TIMODE_DISABLE) + { + assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity)); + assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase)); + + if (hspi->Init.Mode == SPI_MODE_MASTER) + { + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + } + else + { + /* Baudrate prescaler not use in Motoraola Slave mode. force to default value */ + hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + } + } + else + { + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + + /* Force polarity and phase to TI protocaol requirements */ + hspi->Init.CLKPolarity = SPI_POLARITY_LOW; + hspi->Init.CLKPhase = SPI_PHASE_1EDGE; + } +#if (USE_SPI_CRC != 0U) + assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation)); + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial)); + } +#else + hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; +#endif /* USE_SPI_CRC */ + + if (hspi->State == HAL_SPI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hspi->Lock = HAL_UNLOCKED; + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + /* Init the SPI Callback settings */ + hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ + hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */ + hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + + if (hspi->MspInitCallback == NULL) + { + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + hspi->MspInitCallback(hspi); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + HAL_SPI_MspInit(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + + hspi->State = HAL_SPI_STATE_BUSY; + + /* Disable the selected SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + + /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/ + /* Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management, + Communication speed, First bit and CRC calculation state */ + WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) | + (hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) | + (hspi->Init.DataSize & SPI_CR1_DFF) | + (hspi->Init.CLKPolarity & SPI_CR1_CPOL) | + (hspi->Init.CLKPhase & SPI_CR1_CPHA) | + (hspi->Init.NSS & SPI_CR1_SSM) | + (hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) | + (hspi->Init.FirstBit & SPI_CR1_LSBFIRST) | + (hspi->Init.CRCCalculation & SPI_CR1_CRCEN))); + + /* Configure : NSS management */ + WRITE_REG(hspi->Instance->CR2, ((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE)); + +#if (USE_SPI_CRC != 0U) + /*---------------------------- SPIx CRCPOLY Configuration ------------------*/ + /* Configure : CRC Polynomial */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk)); + } +#endif /* USE_SPI_CRC */ + +#if defined(SPI_I2SCFGR_I2SMOD) + /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */ + CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD); +#endif /* SPI_I2SCFGR_I2SMOD */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_READY; + + return HAL_OK; +} + +/** + * @brief De-Initialize the SPI peripheral. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi) +{ + /* Check the SPI handle allocation */ + if (hspi == NULL) + { + return HAL_ERROR; + } + + /* Check SPI Instance parameter */ + assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance)); + + hspi->State = HAL_SPI_STATE_BUSY; + + /* Disable the SPI Peripheral Clock */ + __HAL_SPI_DISABLE(hspi); + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + if (hspi->MspDeInitCallback == NULL) + { + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + hspi->MspDeInitCallback(hspi); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + HAL_SPI_MspDeInit(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Initialize the SPI MSP. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_MspInit should be implemented in the user file + */ +} + +/** + * @brief De-Initialize the SPI MSP. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_MspDeInit should be implemented in the user file + */ +} + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User SPI Callback + * To be used instead of the weak predefined callback + * @param hspi Pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI. + * @param CallbackID ID of the callback to be registered + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, + pSPI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hspi); + + if (HAL_SPI_STATE_READY == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_TX_COMPLETE_CB_ID : + hspi->TxCpltCallback = pCallback; + break; + + case HAL_SPI_RX_COMPLETE_CB_ID : + hspi->RxCpltCallback = pCallback; + break; + + case HAL_SPI_TX_RX_COMPLETE_CB_ID : + hspi->TxRxCpltCallback = pCallback; + break; + + case HAL_SPI_TX_HALF_COMPLETE_CB_ID : + hspi->TxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_RX_HALF_COMPLETE_CB_ID : + hspi->RxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID : + hspi->TxRxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_ERROR_CB_ID : + hspi->ErrorCallback = pCallback; + break; + + case HAL_SPI_ABORT_CB_ID : + hspi->AbortCpltCallback = pCallback; + break; + + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = pCallback; + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPI_STATE_RESET == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = pCallback; + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspi); + return status; +} + +/** + * @brief Unregister an SPI Callback + * SPI callback is redirected to the weak predefined callback + * @param hspi Pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI. + * @param CallbackID ID of the callback to be unregistered + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hspi); + + if (HAL_SPI_STATE_READY == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_TX_COMPLETE_CB_ID : + hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_SPI_RX_COMPLETE_CB_ID : + hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_SPI_TX_RX_COMPLETE_CB_ID : + hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + break; + + case HAL_SPI_TX_HALF_COMPLETE_CB_ID : + hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_SPI_RX_HALF_COMPLETE_CB_ID : + hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID : + hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ + break; + + case HAL_SPI_ERROR_CB_ID : + hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_SPI_ABORT_CB_ID : + hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPI_STATE_RESET == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspi); + return status; +} +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SPI_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SPI + data transfers. + + [..] The SPI supports master and slave mode : + + (#) There are two modes of transfer: + (++) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode: The communication is performed using Interrupts + or DMA, These APIs return the HAL status. + The end of the data processing will be indicated through the + dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected + + (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA) + exist for 1Line (simplex) and 2Lines (full duplex) modes. + +@endverbatim + * @{ + */ + +/** + * @brief Transmit an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + uint16_t initial_TxXferCount; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + initial_TxXferCount = Size; + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (const uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Transmit data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + } + /* Transmit data in 16 Bit mode */ + while (hspi->TxXferCount > 0U) + { + /* Wait until TXE flag is set to send data */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) + { + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + } + /* Transmit data in 8 Bit mode */ + else + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + } + while (hspi->TxXferCount > 0U) + { + /* Wait until TXE flag is set to send data */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + } +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + hspi->State = HAL_SPI_STATE_READY; + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + return HAL_ERROR; + } + else + { + return HAL_OK; + } +} + +/** + * @brief Receive an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + uint32_t tickstart; + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout); + } + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + /* this is done to handle the CRCNEXT before the latest data */ + hspi->RxXferCount--; + } +#endif /* USE_SPI_CRC */ + + /* Configure communication direction: 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Receive data in 8 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_8BIT) + { + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + { + /* Check the RXNE flag */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) + { + /* read the received data */ + (* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint8_t); + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + } + else + { + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + { + /* Check the RXNE flag */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + } + +#if (USE_SPI_CRC != 0U) + /* Handle the CRC Transmission */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* freeze the CRC before the latest data */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + + /* Check if CRCNEXT is well reset by hardware */ + if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT)) + { + /* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */ + CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } + /* Read the latest data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + /* the latest data has not been received */ + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + + /* Receive last data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + } + /* Receive last data in 8 Bit mode */ + else + { + (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR; + } + + /* Wait the CRC data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + + /* Read CRC to Flush DR and RXNE flag */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } +#endif /* USE_SPI_CRC */ + + hspi->State = HAL_SPI_STATE_READY; + /* Unlock the process */ + __HAL_UNLOCK(hspi); + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + return HAL_ERROR; + } + else + { + return HAL_OK; + } +} + +/** + * @brief Transmit and Receive an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @param Size amount of data to be sent and received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size, uint32_t Timeout) +{ + uint16_t initial_TxXferCount; + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Variable used to alternate Rx and Tx during transfer */ + uint32_t txallowed = 1U; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + initial_TxXferCount = Size; + + if (!((tmp_state == HAL_SPI_STATE_READY) || \ + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && + (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + return HAL_BUSY; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferCount = Size; + hspi->RxXferSize = Size; + hspi->pTxBuffPtr = (const uint8_t *)pTxData; + hspi->TxXferCount = Size; + hspi->TxXferSize = Size; + + /*Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Transmit and Receive data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + { + /* Check TXE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U)) + { + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + } + + /* Check RXNE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U)) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + } + if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + /* Transmit and Receive data in 8 Bit mode */ + else + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + { + /* Check TXE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U)) + { + *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + } + + /* Wait until RXNE flag is reset */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U)) + { + (*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR; + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + } + if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U)) + { + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + } + } + +#if (USE_SPI_CRC != 0U) + /* Read CRC from DR to close CRC calculation process */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait until TXE flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + /* Error on the CRC reception */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return HAL_TIMEOUT; + } + /* Read CRC */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } + + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + + hspi->State = HAL_SPI_STATE_READY; + /* Unlock the process */ + __HAL_UNLOCK(hspi); + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + return HAL_ERROR; + } + else + { + return HAL_OK; + } +} + +/** + * @brief Transmit an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size) +{ + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (const uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + hspi->RxISR = NULL; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->TxISR = SPI_TxISR_16BIT; + } + else + { + hspi->TxISR = SPI_TxISR_8BIT; + } + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable TXE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR)); + + return HAL_OK; +} + +/** + * @brief Receive an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size); + } + + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + hspi->TxISR = NULL; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->RxISR = SPI_RxISR_16BIT; + } + else + { + hspi->RxISR = SPI_RxISR_8BIT; + } + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Note : The SPI must be enabled after unlocking current process + to avoid the risk of SPI interrupt handle execution before current + process unlock */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable RXNE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + return HAL_OK; +} + +/** + * @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @param Size amount of data to be sent and received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) +{ + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + + if (!((tmp_state == HAL_SPI_STATE_READY) || \ + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && + (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + return HAL_BUSY; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hspi); + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (const uint8_t *)pTxData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->RxISR = SPI_2linesRxISR_16BIT; + hspi->TxISR = SPI_2linesTxISR_16BIT; + } + else + { + hspi->RxISR = SPI_2linesRxISR_8BIT; + hspi->TxISR = SPI_2linesTxISR_8BIT; + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable TXE, RXNE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR)); + + return HAL_OK; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with DMA. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size) +{ + + /* Check tx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (const uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the SPI TxDMA Half transfer complete callback */ + hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt; + + /* Set the SPI TxDMA transfer complete callback */ + hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt; + + /* Set the DMA error callback */ + hspi->hdmatx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmatx->XferAbortCallback = NULL; + + /* Enable the Tx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, + hspi->TxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Tx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + return HAL_OK; +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA. + * @note In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @note When the CRC feature is enabled the pData Length must be Size + 1. + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + /* Check rx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx)); + + if (hspi->State != HAL_SPI_STATE_READY) + { + return HAL_BUSY; + } + + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + + /* Check tx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size); + } + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the SPI RxDMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt; + + /* Set the SPI Rx DMA transfer complete callback */ + hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt; + + /* Set the DMA error callback */ + hspi->hdmarx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Enable the Rx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, + hspi->RxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Rx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + + return HAL_OK; +} + +/** + * @brief Transmit and Receive an amount of data in non-blocking mode with DMA. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @note When the CRC feature is enabled the pRxData Length must be Size + 1 + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) +{ + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + + /* Check rx & tx dma handles */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx)); + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + + if (!((tmp_state == HAL_SPI_STATE_READY) || + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && + (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + return HAL_BUSY; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hspi); + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (const uint8_t *)pTxData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */ + if (hspi->State == HAL_SPI_STATE_BUSY_RX) + { + /* Set the SPI Rx DMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt; + hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt; + } + else + { + /* Set the SPI Tx/Rx DMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt; + hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt; + } + + /* Set the DMA error callback */ + hspi->hdmarx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Enable the Rx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, + hspi->RxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + + /* Enable Rx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + + /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing + is performed in DMA reception complete callback */ + hspi->hdmatx->XferHalfCpltCallback = NULL; + hspi->hdmatx->XferCpltCallback = NULL; + hspi->hdmatx->XferErrorCallback = NULL; + hspi->hdmatx->XferAbortCallback = NULL; + + /* Enable the Tx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, + hspi->TxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return HAL_ERROR; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Tx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfer (blocking mode). + * @param hspi SPI handle. + * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx), + * started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SPI Interrupts (depending of transfer direction) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode; + __IO uint32_t count; + __IO uint32_t resetcount; + + /* Initialized local variable */ + errorcode = HAL_OK; + resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + count = resetcount; + + /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE); + + /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE)) + { + hspi->TxISR = SPI_AbortTx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE)) + { + hspi->RxISR = SPI_AbortRx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + /* Disable the SPI DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + /* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */ + if (hspi->hdmatx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */ + hspi->hdmatx->XferAbortCallback = NULL; + + /* Abort DMA Tx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN)); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + } + } + + /* Disable the SPI DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + /* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */ + if (hspi->hdmarx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Abort DMA Rx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + + /* Disable peripheral */ + __HAL_SPI_DISABLE(hspi); + + /* Disable Rx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN)); + } + } + /* Reset Tx and Rx transfer counters */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check error during Abort procedure */ + if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT) + { + /* return HAL_Error in case of error during Abort procedure */ + errorcode = HAL_ERROR; + } + else + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + + /* Restore hspi->state to ready */ + hspi->State = HAL_SPI_STATE_READY; + + return errorcode; +} + +/** + * @brief Abort ongoing transfer (Interrupt mode). + * @param hspi SPI handle. + * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx), + * started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SPI Interrupts (depending of transfer direction) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode; + uint32_t abortcplt ; + __IO uint32_t count; + __IO uint32_t resetcount; + + /* Initialized local variable */ + errorcode = HAL_OK; + abortcplt = 1U; + resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + count = resetcount; + + /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE); + + /* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE)) + { + hspi->TxISR = SPI_AbortTx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE)) + { + hspi->RxISR = SPI_AbortRx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + /* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if (hspi->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback; + } + else + { + hspi->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if (hspi->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback; + } + else + { + hspi->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the SPI DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + /* Abort the SPI DMA Tx Stream/Channel */ + if (hspi->hdmatx != NULL) + { + /* Abort DMA Tx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK) + { + hspi->hdmatx->XferAbortCallback = NULL; + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + else + { + abortcplt = 0U; + } + } + } + /* Disable the SPI DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + /* Abort the SPI DMA Rx Stream/Channel */ + if (hspi->hdmarx != NULL) + { + /* Abort DMA Rx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK) + { + hspi->hdmarx->XferAbortCallback = NULL; + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + else + { + abortcplt = 0U; + } + } + } + + if (abortcplt == 1U) + { + /* Reset Tx and Rx transfer counters */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check error during Abort procedure */ + if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT) + { + /* return HAL_Error in case of error during Abort procedure */ + errorcode = HAL_ERROR; + } + else + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + + return errorcode; +} + +/** + * @brief Pause the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi) +{ + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Disable the SPI DMA Tx & Rx requests */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Resume the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi) +{ + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Enable the SPI DMA Tx & Rx requests */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Stop the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + /* The Lock is not implemented on this API to allow the user application + to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or + HAL_SPI_TxRxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or + HAL_SPI_TxRxCpltCallback() + */ + + /* Abort the SPI DMA tx Stream/Channel */ + if (hspi->hdmatx != NULL) + { + if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + /* Abort the SPI DMA rx Stream/Channel */ + if (hspi->hdmarx != NULL) + { + if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + + /* Disable the SPI DMA Tx & Rx requests */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + hspi->State = HAL_SPI_STATE_READY; + return errorcode; +} + +/** + * @brief Handle SPI interrupt request. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval None + */ +void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi) +{ + uint32_t itsource = hspi->Instance->CR2; + uint32_t itflag = hspi->Instance->SR; + + /* SPI in mode Receiver ----------------------------------------------------*/ + if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) && + (SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET)) + { + hspi->RxISR(hspi); + return; + } + + /* SPI in mode Transmitter -------------------------------------------------*/ + if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET)) + { + hspi->TxISR(hspi); + return; + } + + /* SPI in Error Treatment --------------------------------------------------*/ + if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)) + && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET)) + { + /* SPI Overrun error interrupt occurred ----------------------------------*/ + if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET) + { + if (hspi->State != HAL_SPI_STATE_BUSY_TX) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR); + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + else + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + return; + } + } + + /* SPI Mode Fault error interrupt occurred -------------------------------*/ + if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF); + __HAL_SPI_CLEAR_MODFFLAG(hspi); + } + + /* SPI Frame error interrupt occurred ------------------------------------*/ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Disable all interrupts */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR); + + hspi->State = HAL_SPI_STATE_READY; + /* Disable the SPI DMA requests if enabled */ + if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN))) + { + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN)); + + /* Abort the SPI DMA Rx channel */ + if (hspi->hdmarx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */ + hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError; + if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + } + /* Abort the SPI DMA Tx channel */ + if (hspi->hdmatx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */ + hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError; + if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + } + return; + } +} + +/** + * @brief Tx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_RxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Tx and Rx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxRxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxHalfCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file + */ +} + +/** + * @brief Tx and Rx Half Transfer callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file + */ +} + +/** + * @brief SPI error callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_ErrorCallback should be implemented in the user file + */ + /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes + and user can use HAL_SPI_GetError() API to check the latest error occurred + */ +} + +/** + * @brief SPI Abort Complete callback. + * @param hspi SPI handle. + * @retval None + */ +__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief SPI control functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the SPI. + (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral + (+) HAL_SPI_GetError() check in run-time Errors occurring during communication +@endverbatim + * @{ + */ + +/** + * @brief Return the SPI handle state. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval SPI state + */ +HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi) +{ + /* Return SPI handle state */ + return hspi->State; +} + +/** + * @brief Return the SPI error code. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval SPI error code in bitmap format + */ +uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi) +{ + /* Return SPI ErrorCode */ + return hspi->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Functions + * @brief Private functions + * @{ + */ + +/** + * @brief DMA SPI transmit process complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + uint32_t tickstart; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received data is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + hspi->TxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user Tx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxCpltCallback(hspi); +#else + HAL_SPI_TxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI receive process complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + +#if (USE_SPI_CRC != 0U) + /* CRC handling */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait until RXNE flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + /* Error on the CRC reception */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + } + /* Read CRC */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check if we are in Master RX 2 line mode */ + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + /* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + } + else + { + /* Normal case */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + } + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + + hspi->RxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI transmit receive process complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + +#if (USE_SPI_CRC != 0U) + /* CRC handling */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait the CRC data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + } + /* Read CRC to Flush DR and RXNE flag */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Disable Rx/Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + hspi->TxXferCount = 0U; + hspi->RxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user TxRx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxCpltCallback(hspi); +#else + HAL_SPI_TxRxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half transmit process complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Call user Tx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxHalfCpltCallback(hspi); +#else + HAL_SPI_TxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half receive process complete callback + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Call user Rx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxHalfCpltCallback(hspi); +#else + HAL_SPI_RxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half transmit receive process complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Call user TxRx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxHalfCpltCallback(hspi); +#else + HAL_SPI_TxRxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI communication error callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SPI_DMAError(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Stop the disable DMA transfer on SPI side */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + hspi->State = HAL_SPI_STATE_READY; + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + __IO uint32_t count; + + hspi->hdmatx->XferAbortCallback = NULL; + count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Check if an Abort process is still ongoing */ + if (hspi->hdmarx != NULL) + { + if (hspi->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check no error during Abort procedure */ + if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT) + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + hspi->hdmarx->XferAbortCallback = NULL; + + /* Disable Rx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + + /* Check Busy flag */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + + /* Check if an Abort process is still ongoing */ + if (hspi->hdmatx != NULL) + { + if (hspi->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check no error during Abort procedure */ + if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT) + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Receive data in 8bit mode */ + *hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR); + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + + /* Check end of the reception */ + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_2linesRxISR_8BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint8_t *ptmpreg8; + __IO uint8_t tmpreg8 = 0; + + /* Initialize the 8bit temporary pointer */ + ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR; + /* Read 8bit CRC to flush Data Register */ + tmpreg8 = *ptmpreg8; + /* To avoid GCC warning */ + UNUSED(tmpreg8); + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + + /* Check the end of the transmission */ + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Set CRC Next Bit to send CRC */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + + if (hspi->RxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +/** + * @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Receive data in 16 Bit mode */ + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR); + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_2linesRxISR_16BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable RXNE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + + /* Read 16bit CRC to flush Data Register */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + /* Disable RXNE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE); + + SPI_CloseRxTx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Transmit data in 16 Bit mode */ + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + + /* Enable CRC Transmission */ + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Set CRC Next Bit to send CRC */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + + if (hspi->RxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 8-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint8_t *ptmpreg8; + __IO uint8_t tmpreg8 = 0; + + /* Initialize the 8bit temporary pointer */ + ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR; + /* Read 8bit CRC to flush Data Register */ + tmpreg8 = *ptmpreg8; + /* To avoid GCC warning */ + UNUSED(tmpreg8); + + SPI_CloseRx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Manage the receive 8-bit in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR); + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } + /* Check if CRCNEXT is well reset by hardware */ + if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT)) + { + /* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */ + CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } + +#endif /* USE_SPI_CRC */ + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_RxISR_8BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + SPI_CloseRx_ISR(hspi); + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 16-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + + /* Read 16bit CRC to flush Data Register */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + SPI_CloseRx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Manage the 16-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR); + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } + /* Check if CRCNEXT is well reset by hardware */ + if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT)) + { + /* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */ + CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } + +#endif /* USE_SPI_CRC */ + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_RxISR_16BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + SPI_CloseRx_ISR(hspi); + } +} + +/** + * @brief Handle the data 8-bit transmit in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Enable CRC Transmission */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + SPI_CloseTx_ISR(hspi); + } +} + +/** + * @brief Handle the data 16-bit transmit in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Transmit data in 16 Bit mode */ + hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Enable CRC Transmission */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + SPI_CloseTx_ISR(hspi); + } +} + +/** + * @brief Handle SPI Communication Timeout. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param Flag SPI flag to check + * @param State flag state to check + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State, + uint32_t Timeout, uint32_t Tickstart) +{ + __IO uint32_t count; + uint32_t tmp_timeout; + uint32_t tmp_tickstart; + + /* Adjust Timeout value in case of end of transfer */ + tmp_timeout = Timeout - (HAL_GetTick() - Tickstart); + tmp_tickstart = HAL_GetTick(); + + /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */ + count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U); + + while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State) + { + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U)) + { + /* Disable the SPI and reset the CRC: the CRC value should be cleared + on both master and slave sides in order to resynchronize the master + and slave for their respective CRC calculation */ + + /* Disable TXE, RXNE and ERR interrupts for the interrupt process */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR)); + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE) + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + { + /* Disable SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + } + + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } + + hspi->State = HAL_SPI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_TIMEOUT; + } + /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */ + if (count == 0U) + { + tmp_timeout = 0U; + } + count--; + } + } + + return HAL_OK; +} + +/** + * @brief Handle the check of the RX transaction complete. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart) +{ + if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE) + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + { + /* Disable SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + } + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)) + { + /* Wait the RXNE reset */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + else + { + /* Control the BSY flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief Handle the check of the RXTX or TX transaction complete. + * @param hspi SPI handle + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until TXE flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_TXE, SET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + + /* Control the BSY flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + return HAL_OK; +} + +/** + * @brief Handle the end of the RXTX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi) +{ + uint32_t tickstart; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + hspi->State = HAL_SPI_STATE_READY; + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } + else + { +#endif /* USE_SPI_CRC */ + if (hspi->ErrorCode == HAL_SPI_ERROR_NONE) + { + if (hspi->State == HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxCpltCallback(hspi); +#else + HAL_SPI_TxRxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + } + else + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +#if (USE_SPI_CRC != 0U) + } +#endif /* USE_SPI_CRC */ +} + +/** + * @brief Handle the end of the RX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi) +{ + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + /* Check if CRC error is valid or not (workaround to be applied or not) */ + if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + + /* Reset CRC Calculation */ + SPI_RESET_CRC(hspi); + + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } + } + else + { +#endif /* USE_SPI_CRC */ + if (hspi->ErrorCode == HAL_SPI_ERROR_NONE) + { + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +#if (USE_SPI_CRC != 0U) + } +#endif /* USE_SPI_CRC */ +} + +/** + * @brief Handle the end of the TX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi) +{ + uint32_t tickstart; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Disable TXE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR)); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + hspi->State = HAL_SPI_STATE_READY; + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxCpltCallback(hspi); +#else + HAL_SPI_TxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Handle abort a Rx transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE)); + + /* Flush Data Register by a blank read */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + hspi->State = HAL_SPI_STATE_ABORT; +} + +/** + * @brief Handle abort a Tx or Rx/Tx transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi) +{ + /* Disable TXEIE interrupt */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE)); + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + hspi->State = HAL_SPI_STATE_ABORT; +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Checks if encountered CRC error could be corresponding to wrongly detected errors + * according to SPI instance, Device type, and revision ID. + * @param hspi: pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval CRC error validity (SPI_INVALID_CRC_ERROR or SPI_VALID_CRC_ERROR). + */ +uint8_t SPI_ISCRCErrorValid(SPI_HandleTypeDef *hspi) +{ +#if defined(SPI_CRC_ERROR_WORKAROUND_FEATURE) && (USE_SPI_CRC_ERROR_WORKAROUND != 0U) + /* Check how to handle this CRC error (workaround to be applied or not) */ + /* If CRC errors could be wrongly detected (issue 2.15.2 in STM32F10xxC/D/E silicon limitations ES + (DocID14732 Rev 13)) */ + if (hspi->Instance == SPI2) + { + if (hspi->Instance->RXCRCR == 0U) + { + return (SPI_INVALID_CRC_ERROR); + } + } +#endif /* USE_SPI_CRC_ERROR_WORKAROUND */ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + return (SPI_VALID_CRC_ERROR); +} +#endif /* USE_SPI_CRC */ +/** + * @} + */ + +#endif /* HAL_SPI_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx b/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx index cd9a0c1..ccc8d00 100644 --- a/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx +++ b/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx @@ -81,7 +81,7 @@ 0 - 0 + 1 0 @@ -340,7 +340,7 @@ USE_HAL_DRIVER,STM32F103xB - ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include + ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP/MultiButton;..\Drivers\BSP\LCD @@ -404,6 +404,118 @@ 1 ../Core/Src/gpio.c + + dma.c + 1 + ../Core/Src/dma.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + spi.c + 1 + ../Core/Src/spi.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + usart.c 1 @@ -430,9 +542,60 @@ ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c - stm32f1xx_hal_uart.c + stm32f1xx_hal_spi.c 1 - ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c + ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + stm32f1xx_hal.c @@ -484,6 +647,11 @@ 1 ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c + + stm32f1xx_hal_uart.c + 1 + ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c + @@ -496,6 +664,31 @@ + + Drivers/BSP + + + lcd_data.c + 1 + ..\Drivers\BSP\LCD\lcd_data.c + + + st7735s.c + 1 + ..\Drivers\BSP\LCD\st7735s.c + + + button_driver.c + 1 + ..\Drivers\BSP\MultiButton\button_driver.c + + + multi_button.c + 1 + ..\Drivers\BSP\MultiButton\multi_button.c + + + ::CMSIS @@ -516,4 +709,13 @@ + + + + STM32F103C8T6 + 1 + + + + diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp index 4251f36..c1e6e3e 100644 --- a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp +++ b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp @@ -2,11 +2,13 @@ "stm32f103c8t6\startup_stm32f103xb.o" "stm32f103c8t6\main.o" "stm32f103c8t6\gpio.o" +"stm32f103c8t6\dma.o" +"stm32f103c8t6\spi.o" "stm32f103c8t6\usart.o" "stm32f103c8t6\stm32f1xx_it.o" "stm32f103c8t6\stm32f1xx_hal_msp.o" "stm32f103c8t6\stm32f1xx_hal_gpio_ex.o" -"stm32f103c8t6\stm32f1xx_hal_uart.o" +"stm32f103c8t6\stm32f1xx_hal_spi.o" "stm32f103c8t6\stm32f1xx_hal.o" "stm32f103c8t6\stm32f1xx_hal_rcc.o" "stm32f103c8t6\stm32f1xx_hal_rcc_ex.o" @@ -17,7 +19,12 @@ "stm32f103c8t6\stm32f1xx_hal_flash.o" "stm32f103c8t6\stm32f1xx_hal_flash_ex.o" "stm32f103c8t6\stm32f1xx_hal_exti.o" +"stm32f103c8t6\stm32f1xx_hal_uart.o" "stm32f103c8t6\system_stm32f1xx.o" +"stm32f103c8t6\lcd_data.o" +"stm32f103c8t6\st7735s_1.o" +"stm32f103c8t6\button_driver_1.o" +"stm32f103c8t6\multi_button_1.o" --library_type=microlib --strict --scatter "STM32F103C8T6\STM32F103C8T6.sct" --summary_stderr --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/button_driver_1.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/button_driver_1.crf new file mode 100644 index 0000000..5d4dd55 Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/button_driver_1.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/dma.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/dma.crf new file mode 100644 index 0000000..323500e Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/dma.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/gpio.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/gpio.crf index 1ece49d..d774b22 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/gpio.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/gpio.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf new file mode 100644 index 0000000..180fde2 Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf index d4ff3ca..a1f85b6 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/multi_button_1.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/multi_button_1.crf new file mode 100644 index 0000000..bba2cb2 Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/multi_button_1.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/spi.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/spi.crf new file mode 100644 index 0000000..16193bb Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/spi.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf new file mode 100644 index 0000000..af2a3ba Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal.crf index 6819d8c..c6955bb 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_cortex.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_cortex.crf index ef7dcbe..f5b003e 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_cortex.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_cortex.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_dma.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_dma.crf index 8188d63..c8c3d09 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_dma.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_dma.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_exti.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_exti.crf index 96180fe..bac9ade 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_exti.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_exti.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash.crf index 79a4678..6c0e2af 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash_ex.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash_ex.crf index f5c9533..7622ae8 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash_ex.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_flash_ex.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio.crf index 7770c83..62a3834 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio_ex.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio_ex.crf index 709ab78..5099039 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio_ex.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_gpio_ex.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_msp.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_msp.crf index a6736d9..247432d 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_msp.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_msp.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_pwr.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_pwr.crf index 575f178..0ac4f66 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_pwr.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_pwr.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc.crf index be866ce..1b745ca 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc_ex.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc_ex.crf index 4502402..1c4c153 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc_ex.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_rcc_ex.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_spi.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_spi.crf new file mode 100644 index 0000000..6b62bd1 Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_spi.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_uart.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_uart.crf index fb8f0a8..02c0a3f 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_uart.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_hal_uart.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_it.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_it.crf index 8be57d4..e2be534 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_it.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/stm32f1xx_it.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/system_stm32f1xx.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/system_stm32f1xx.crf index 1404a93..492136a 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/system_stm32f1xx.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/system_stm32f1xx.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/usart.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/usart.crf index 9664389..205c92c 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/usart.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/usart.crf differ diff --git a/STM32F103C8T6/STM32F103C8T6.ioc b/STM32F103C8T6/STM32F103C8T6.ioc index e176aef..82ec7cf 100644 --- a/STM32F103C8T6/STM32F103C8T6.ioc +++ b/STM32F103C8T6/STM32F103C8T6.ioc @@ -2,41 +2,57 @@ CAD.formats= CAD.pinconfig= CAD.provider= +Dma.Request0=SPI2_TX +Dma.RequestsNb=1 +Dma.SPI2_TX.0.Direction=DMA_MEMORY_TO_PERIPH +Dma.SPI2_TX.0.Instance=DMA1_Channel5 +Dma.SPI2_TX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.SPI2_TX.0.MemInc=DMA_MINC_ENABLE +Dma.SPI2_TX.0.Mode=DMA_NORMAL +Dma.SPI2_TX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.SPI2_TX.0.PeriphInc=DMA_PINC_DISABLE +Dma.SPI2_TX.0.Priority=DMA_PRIORITY_LOW +Dma.SPI2_TX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority File.Version=6 GPIO.groupedBy=Group By Peripherals KeepUserPlacement=false Mcu.CPN=STM32F103C8T6 Mcu.Family=STM32F1 -Mcu.IP0=NVIC -Mcu.IP1=RCC -Mcu.IP2=SYS -Mcu.IP3=USART1 -Mcu.IPNb=4 +Mcu.IP0=DMA +Mcu.IP1=NVIC +Mcu.IP2=RCC +Mcu.IP3=SPI2 +Mcu.IP4=SYS +Mcu.IP5=USART1 +Mcu.IPNb=6 Mcu.Name=STM32F103C(8-B)Tx Mcu.Package=LQFP48 Mcu.Pin0=PC13-TAMPER-RTC Mcu.Pin1=PC14-OSC32_IN -Mcu.Pin10=PA13 -Mcu.Pin11=PA14 -Mcu.Pin12=PB3 -Mcu.Pin13=PB4 -Mcu.Pin14=PB5 -Mcu.Pin15=VP_SYS_VS_Systick +Mcu.Pin10=PA9 +Mcu.Pin11=PA10 +Mcu.Pin12=PA13 +Mcu.Pin13=PA14 +Mcu.Pin14=PB3 +Mcu.Pin15=PB4 +Mcu.Pin16=PB5 +Mcu.Pin17=VP_SYS_VS_Systick Mcu.Pin2=PC15-OSC32_OUT Mcu.Pin3=PD0-OSC_IN Mcu.Pin4=PD1-OSC_OUT -Mcu.Pin5=PB12 -Mcu.Pin6=PB13 -Mcu.Pin7=PB15 -Mcu.Pin8=PA9 -Mcu.Pin9=PA10 -Mcu.PinsNb=16 +Mcu.Pin5=PB10 +Mcu.Pin6=PB11 +Mcu.Pin7=PB12 +Mcu.Pin8=PB13 +Mcu.Pin9=PB15 +Mcu.PinsNb=18 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F103C8Tx MxCube.Version=6.17.0 MxDb.Version=DB.6.0.170 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false @@ -55,24 +71,31 @@ PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PB10.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label +PB10.GPIO_Label=LCD_DC +PB10.GPIO_PuPd=GPIO_PULLUP +PB10.GPIO_Speed=GPIO_SPEED_FREQ_HIGH +PB10.Locked=true +PB10.Signal=GPIO_Output +PB11.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label +PB11.GPIO_Label=LCD_CS +PB11.GPIO_PuPd=GPIO_PULLUP +PB11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH +PB11.Locked=true +PB11.PinState=GPIO_PIN_RESET +PB11.Signal=GPIO_Output PB12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label PB12.GPIO_Label=LCD_RST PB12.GPIO_PuPd=GPIO_PULLUP PB12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PB12.Locked=true PB12.Signal=GPIO_Output -PB13.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label -PB13.GPIO_Label=LCD_SCL -PB13.GPIO_PuPd=GPIO_PULLUP -PB13.GPIO_Speed=GPIO_SPEED_FREQ_HIGH PB13.Locked=true -PB13.Signal=GPIO_Output -PB15.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label -PB15.GPIO_Label=LCD_SDA -PB15.GPIO_PuPd=GPIO_PULLUP -PB15.GPIO_Speed=GPIO_SPEED_FREQ_HIGH +PB13.Mode=TX_Only_Simplex_Unidirect_Master +PB13.Signal=SPI2_SCK PB15.Locked=true -PB15.Signal=GPIO_Output +PB15.Mode=TX_Only_Simplex_Unidirect_Master +PB15.Signal=SPI2_MOSI PB3.GPIOParameters=GPIO_PuPd,GPIO_Label PB3.GPIO_Label=KEY3 PB3.GPIO_PuPd=GPIO_PULLDOWN @@ -150,7 +173,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_USART1_UART_Init-USART1-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true RCC.ADCFreqValue=36000000 RCC.AHBFreq_Value=72000000 RCC.APB1CLKDivider=RCC_HCLK_DIV2 @@ -172,6 +195,12 @@ RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK RCC.TimSysFreq_Value=72000000 RCC.USBFreq_Value=72000000 RCC.VCOOutput2Freq_Value=8000000 +SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2 +SPI2.CalculateBaudRate=18.0 MBits/s +SPI2.Direction=SPI_DIRECTION_2LINES +SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler +SPI2.Mode=SPI_MODE_MASTER +SPI2.VirtualType=VM_MASTER USART1.IPParameters=VirtualMode USART1.VirtualMode=VM_ASYNC VP_SYS_VS_Systick.Mode=SysTick