diff --git a/.vscode/settings.json b/.vscode/settings.json index 3cf2627..eaab07f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "files.associations": { - "user_math.h": "c" + "user_math.h": "c", + "bsp.h": "c", + "stdint.h": "c" } } \ No newline at end of file diff --git a/app/__pycache__/__init__.cpython-39.pyc b/app/__pycache__/__init__.cpython-39.pyc index 3462ec2..8636fd1 100644 Binary files a/app/__pycache__/__init__.cpython-39.pyc and b/app/__pycache__/__init__.cpython-39.pyc differ diff --git a/app/code_page/bsp_interface.py b/app/code_page/bsp_interface.py index 099e9cd..cfb5892 100644 --- a/app/code_page/bsp_interface.py +++ b/app/code_page/bsp_interface.py @@ -366,6 +366,14 @@ def get_available_gpio(project_path): return analyzing_ioc.get_enabled_gpio_from_ioc(ioc_path) return [] +def get_available_pwm(project_path): + """获取可用的PWM通道""" + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_pwm_from_ioc(ioc_path) + return [] + # 具体外设类 class bsp_i2c(BspPeripheralBase): def __init__(self, project_path): @@ -391,6 +399,70 @@ class bsp_can(BspPeripheralBase): get_available_can ) + def _generate_source_file(self, configs, template_dir): + template_path = os.path.join(template_dir, self.template_names['source']) + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + + # Get函数 + get_lines = [] + for idx, (name, instance) in enumerate(configs): + if idx == 0: + get_lines.append(f" if (hcan->Instance == {instance})") + else: + get_lines.append(f" else if (hcan->Instance == {instance})") + get_lines.append(f" return {self.enum_prefix}_{name};") + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED CAN_GET", "\n".join(get_lines) + ) + + # Handle函数 + handle_lines = [] + for name, instance in configs: + handle_lines.append(f" case {self.enum_prefix}_{name}:") + handle_lines.append(f" return &h{instance.lower()};") + content = CodeGenerator.replace_auto_generated( + content, f"AUTO GENERATED {self.enum_prefix}_GET_HANDLE", "\n".join(handle_lines) + ) + + # 生成CAN初始化代码 + init_lines = [] + for idx, (name, instance) in enumerate(configs): + can_num = instance[-1] # CAN1 -> 1, CAN2 -> 2 + + init_lines.append(f" // 初始化 {instance}") + init_lines.append(f" CAN_FilterTypeDef can{can_num}_filter = {{0}};") + init_lines.append(f" can{can_num}_filter.FilterBank = {0 if can_num == '1' else 14};") + init_lines.append(f" can{can_num}_filter.FilterIdHigh = 0;") + init_lines.append(f" can{can_num}_filter.FilterIdLow = 0;") + init_lines.append(f" can{can_num}_filter.FilterMode = CAN_FILTERMODE_IDMASK;") + init_lines.append(f" can{can_num}_filter.FilterScale = CAN_FILTERSCALE_32BIT;") + init_lines.append(f" can{can_num}_filter.FilterMaskIdHigh = 0;") + init_lines.append(f" can{can_num}_filter.FilterMaskIdLow = 0;") + init_lines.append(f" can{can_num}_filter.FilterActivation = ENABLE;") + if can_num == '1': + init_lines.append(f" can{can_num}_filter.SlaveStartFilterBank = 14;") + init_lines.append(f" can{can_num}_filter.FilterFIFOAssignment = CAN_RX_FIFO0;") + else: + init_lines.append(f" can{can_num}_filter.FilterFIFOAssignment = CAN_RX_FIFO1;") + + init_lines.append(f" HAL_CAN_ConfigFilter(BSP_CAN_GetHandle({self.enum_prefix}_{name}), &can{can_num}_filter);") + init_lines.append(f" HAL_CAN_Start(BSP_CAN_GetHandle({self.enum_prefix}_{name}));") + + # 注册回调和激活中断 + fifo = "FIFO0" if can_num == '1' else "FIFO1" + init_lines.append(f" HAL_CAN_ActivateNotification(BSP_CAN_GetHandle({self.enum_prefix}_{name}), CAN_IT_RX_{fifo}_MSG_PENDING);") + init_lines.append("") + + content = CodeGenerator.replace_auto_generated( + content, "AUTO GENERATED CAN_INIT", "\n".join(init_lines) + ) + + output_path = os.path.join(self.project_path, f"User/bsp/{self.template_names['source']}") + save_with_preserve(output_path, content) + return True + class bsp_spi(BspPeripheralBase): def __init__(self, project_path): super().__init__( @@ -419,19 +491,30 @@ class bsp_gpio(QWidget): def __init__(self, project_path): super().__init__() self.project_path = project_path - self.available_list = get_available_gpio(project_path) - # 新增:加载描述 + self.available_list = self._get_all_gpio_list() + # 加载描述 describe_path = os.path.join(os.path.dirname(__file__), "../../assets/User_code/bsp/describe.csv") self.descriptions = load_descriptions(describe_path) self._init_ui() + self._load_config() + + def _get_all_gpio_list(self): + """获取所有GPIO配置""" + ioc_files = [f for f in os.listdir(self.project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(self.project_path, ioc_files[0]) + return analyzing_ioc.get_all_gpio_from_ioc(ioc_path) + return [] def _init_ui(self): layout = QVBoxLayout(self) + # 顶部布局 top_layout = QHBoxLayout() top_layout.setAlignment(Qt.AlignVCenter) self.generate_checkbox = CheckBox("生成 GPIO 代码") + self.generate_checkbox.stateChanged.connect(self._on_generate_changed) top_layout.addWidget(self.generate_checkbox, alignment=Qt.AlignLeft) top_layout.addStretch() @@ -449,77 +532,407 @@ class bsp_gpio(QWidget): desc_label = BodyLabel(f"功能说明:{desc}") desc_label.setWordWrap(True) layout.addWidget(desc_label) + + # 内容区域 + self.content_widget = QWidget() + content_layout = QVBoxLayout(self.content_widget) + if not self.available_list: - layout.addWidget(BodyLabel("在 .ioc 文件中未找到可用的 GPIO")) + content_layout.addWidget(BodyLabel("在 .ioc 文件中未找到可用的 GPIO")) else: + # 创建表格 self.table = TableWidget() - self.table.setColumnCount(1) - self.table.setRowCount(len(self.available_list)) - self.table.setHorizontalHeaderLabels(["Label"]) + self.table.setColumnCount(4) + self.table.setHorizontalHeaderLabels(["IOC Label", "自定义名称", "类型", "包含"]) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) - for row, item in enumerate(self.available_list): + + # 填充表格 + for row, gpio_info in enumerate(self.available_list): + self.table.insertRow(row) + + # IOC Label (只读) from PyQt5.QtWidgets import QTableWidgetItem - self.table.setItem(row, 0, QTableWidgetItem(item['label'])) - self.table.setEditTriggers(TableWidget.NoEditTriggers) - layout.addWidget(self.table) + label_item = QTableWidgetItem(gpio_info['label']) + label_item.setFlags(label_item.flags() & ~Qt.ItemIsEditable) + self.table.setItem(row, 0, label_item) + + # 自定义名称 (可编辑) + name_edit = LineEdit() + name_edit.setText(gpio_info['label']) # 默认使用IOC的label + name_edit.setPlaceholderText("输入自定义名称") + self.table.setCellWidget(row, 1, name_edit) + + # 类型显示 + gpio_type = "EXTI" if gpio_info['has_exti'] else ("输出" if gpio_info['is_output'] else "输入") + type_item = QTableWidgetItem(gpio_type) + type_item.setFlags(type_item.flags() & ~Qt.ItemIsEditable) + self.table.setItem(row, 2, type_item) + + # 包含复选框 + include_checkbox = CheckBox("") + include_checkbox.setChecked(True) # 默认选中 + self.table.setCellWidget(row, 3, include_checkbox) + + content_layout.addWidget(self.table) + + layout.addWidget(self.content_widget) + self.content_widget.setEnabled(False) + + def _on_generate_changed(self, state): + self.content_widget.setEnabled(state == 2) def is_need_generate(self): return self.generate_checkbox.isChecked() and bool(self.available_list) + def _collect_configs(self): + """收集用户配置""" + configs = [] + for row in range(self.table.rowCount()): + include_widget = self.table.cellWidget(row, 3) + if include_widget and include_widget.isChecked(): + name_widget = self.table.cellWidget(row, 1) + if name_widget: + custom_name = name_widget.text().strip() + if custom_name: + gpio_info = self.available_list[row] + configs.append({ + 'custom_name': custom_name.upper(), + 'ioc_label': gpio_info['label'], + 'pin': gpio_info['pin'], + 'has_exti': gpio_info['has_exti'] + }) + return configs + def _generate_bsp_code_internal(self): if not self.is_need_generate(): return False + + configs = self._collect_configs() + if not configs: + return False + template_dir = CodeGenerator.get_template_dir() - if not self._generate_header_file(template_dir): + if not self._generate_header_file(configs, template_dir): return False - if not self._generate_source_file(template_dir): + if not self._generate_source_file(configs, template_dir): return False - self._save_config() + self._save_config(configs) return True - def _generate_header_file(self, template_dir): + def _generate_header_file(self, configs, template_dir): template_path = os.path.join(template_dir, "gpio.h") template_content = CodeGenerator.load_template(template_path) if not template_content: return False + + # 生成枚举 + enum_lines = [] + for config in configs: + enum_lines.append(f" BSP_GPIO_{config['custom_name']},") + + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED BSP_GPIO_ENUM", "\n".join(enum_lines) + ) + output_path = os.path.join(self.project_path, "User/bsp/gpio.h") - save_with_preserve(output_path, template_content) # 使用保留用户区域的写入 + save_with_preserve(output_path, content) return True - def _generate_source_file(self, template_dir): + def _generate_source_file(self, configs, template_dir): template_path = os.path.join(template_dir, "gpio.c") template_content = CodeGenerator.load_template(template_path) if not template_content: return False + + # 生成MAP数组 + map_lines = [] + for config in configs: + ioc_label = config['ioc_label'] + map_lines.append(f" {{{ioc_label}_Pin, {ioc_label}_GPIO_Port}},") + + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED BSP_GPIO_MAP", "\n".join(map_lines) + ) + + # 生成EXTI使能代码 enable_lines = [] disable_lines = [] - for item in self.available_list: - label = item['label'] - enable_lines.append(f" case {label}_Pin:") - enable_lines.append(f" HAL_NVIC_EnableIRQ({label}_EXTI_IRQn);") - enable_lines.append(f" break;") - disable_lines.append(f" case {label}_Pin:") - disable_lines.append(f" HAL_NVIC_DisableIRQ({label}_EXTI_IRQn);") - disable_lines.append(f" break;") + for config in configs: + if config['has_exti']: + ioc_label = config['ioc_label'] + enable_lines.append(f" case {ioc_label}_Pin:") + enable_lines.append(f" HAL_NVIC_EnableIRQ({ioc_label}_EXTI_IRQn);") + enable_lines.append(f" break;") + disable_lines.append(f" case {ioc_label}_Pin:") + disable_lines.append(f" HAL_NVIC_DisableIRQ({ioc_label}_EXTI_IRQn);") + disable_lines.append(f" break;") + content = CodeGenerator.replace_auto_generated( - template_content, "AUTO GENERATED BSP_GPIO_ENABLE_IRQ", "\n".join(enable_lines) + content, "AUTO GENERATED BSP_GPIO_ENABLE_IRQ", "\n".join(enable_lines) ) content = CodeGenerator.replace_auto_generated( content, "AUTO GENERATED BSP_GPIO_DISABLE_IRQ", "\n".join(disable_lines) ) + output_path = os.path.join(self.project_path, "User/bsp/gpio.c") - save_with_preserve(output_path, content) # 使用保留用户区域的写入 + save_with_preserve(output_path, content) return True - def _save_config(self): + def _save_config(self, configs): config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml") config_data = CodeGenerator.load_config(config_path) config_data['gpio'] = { 'enabled': True, - 'labels': [item['label'] for item in self.available_list] + 'configs': [ + { + 'custom_name': config['custom_name'], + 'ioc_label': config['ioc_label'], + 'pin': config['pin'], + 'has_exti': config['has_exti'] + } for config in configs + ] } CodeGenerator.save_config(config_data, config_path) + def _load_config(self): + config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml") + config_data = CodeGenerator.load_config(config_path) + conf = config_data.get('gpio', {}) + if conf.get('enabled', False): + self.generate_checkbox.setChecked(True) + saved_configs = conf.get('configs', []) + # 恢复用户的自定义名称和选择状态 + for saved_config in saved_configs: + for row in range(len(self.available_list)): + if (self.available_list[row]['label'] == saved_config['ioc_label'] and + hasattr(self, 'table')): + name_widget = self.table.cellWidget(row, 1) + if name_widget: + name_widget.setText(saved_config['custom_name']) + +class bsp_pwm(QWidget): + def __init__(self, project_path): + super().__init__() + self.project_path = project_path + self.available_list = self._get_pwm_channels() + # 加载描述 + describe_path = os.path.join(os.path.dirname(__file__), "../../assets/User_code/bsp/describe.csv") + self.descriptions = load_descriptions(describe_path) + self._init_ui() + self._load_config() + + def _get_pwm_channels(self): + """获取所有PWM通道配置""" + return get_available_pwm(self.project_path) + + def _init_ui(self): + layout = QVBoxLayout(self) + + # 顶部布局 + top_layout = QHBoxLayout() + top_layout.setAlignment(Qt.AlignVCenter) + + self.generate_checkbox = CheckBox("生成 PWM 代码") + self.generate_checkbox.stateChanged.connect(self._on_generate_changed) + top_layout.addWidget(self.generate_checkbox, alignment=Qt.AlignLeft) + + top_layout.addStretch() + + title = SubtitleLabel("PWM 配置 ") + title.setAlignment(Qt.AlignHCenter) + top_layout.addWidget(title, alignment=Qt.AlignHCenter) + + top_layout.addStretch() + + layout.addLayout(top_layout) + + desc = self.descriptions.get("pwm", "") + if desc: + desc_label = BodyLabel(f"功能说明:{desc}") + desc_label.setWordWrap(True) + layout.addWidget(desc_label) + + # 内容区域 + self.content_widget = QWidget() + content_layout = QVBoxLayout(self.content_widget) + + if not self.available_list: + content_layout.addWidget(BodyLabel("在 .ioc 文件中未找到可用的 PWM 通道")) + else: + # 创建表格 + self.table = TableWidget() + self.table.setColumnCount(4) + self.table.setHorizontalHeaderLabels(["PWM通道", "自定义名称", "定时器信息", "选择"]) + + # 设置列宽度 - 手动调整各列的初始宽度 + header = self.table.horizontalHeader() + header.setSectionResizeMode(0, QHeaderView.Interactive) # PWM通道列可调整 + header.setSectionResizeMode(1, QHeaderView.Stretch) # 自定义名称列拉伸 + header.setSectionResizeMode(2, QHeaderView.Interactive) # 定时器信息列可调整 + header.setSectionResizeMode(3, QHeaderView.Fixed) # 选择列固定宽度 + + # 设置初始列宽 + self.table.setColumnWidth(0, 150) # PWM通道列宽度 + self.table.setColumnWidth(2, 120) # 定时器信息列宽度 + self.table.setColumnWidth(3, 80) # 选择列宽度 + + # 填充表格 + for row, pwm_info in enumerate(self.available_list): + self.table.insertRow(row) + + # PWM通道信息 (只读) - 显示完整的通道信息 + from PyQt5.QtWidgets import QTableWidgetItem + channel_display = f"{pwm_info['timer']} {pwm_info['channel'].replace('TIM_CHANNEL_', 'CH')}" + channel_item = QTableWidgetItem(channel_display) + channel_item.setFlags(channel_item.flags() & ~Qt.ItemIsEditable) + self.table.setItem(row, 0, channel_item) + + # 自定义名称 (可编辑) + name_edit = LineEdit() + name_edit.setText(pwm_info['label']) # 默认使用IOC的label + name_edit.setPlaceholderText("输入自定义名称") + self.table.setCellWidget(row, 1, name_edit) + + # 定时器信息 - 显示引脚和信号 + timer_info = f"{pwm_info['pin']}" + timer_item = QTableWidgetItem(timer_info) + timer_item.setFlags(timer_item.flags() & ~Qt.ItemIsEditable) + self.table.setItem(row, 2, timer_item) + + # 选择复选框 - 放在中央 + checkbox_widget = QWidget() + checkbox_layout = QHBoxLayout(checkbox_widget) + checkbox_layout.setContentsMargins(0, 0, 0, 0) + checkbox_layout.setAlignment(Qt.AlignCenter) + + include_checkbox = CheckBox("") + include_checkbox.setChecked(True) # 默认选中 + checkbox_layout.addWidget(include_checkbox) + + self.table.setCellWidget(row, 3, checkbox_widget) + + content_layout.addWidget(self.table) + + layout.addWidget(self.content_widget) + self.content_widget.setEnabled(False) + + def _on_generate_changed(self, state): + self.content_widget.setEnabled(state == 2) + + def is_need_generate(self): + return self.generate_checkbox.isChecked() and bool(self.available_list) + + def _collect_configs(self): + """收集用户配置""" + configs = [] + for row in range(self.table.rowCount()): + checkbox_widget = self.table.cellWidget(row, 3) + if checkbox_widget: + # 获取复选框 + include_checkbox = checkbox_widget.findChild(CheckBox) + if include_checkbox and include_checkbox.isChecked(): + name_widget = self.table.cellWidget(row, 1) + if name_widget: + custom_name = name_widget.text().strip() + if custom_name: + pwm_info = self.available_list[row] + configs.append({ + 'custom_name': custom_name.upper(), + 'timer': pwm_info['timer'], + 'channel': pwm_info['channel'], + 'label': pwm_info['label'] + }) + return configs + + def _generate_bsp_code_internal(self): + if not self.is_need_generate(): + return False + + configs = self._collect_configs() + if not configs: + return False + + template_dir = CodeGenerator.get_template_dir() + if not self._generate_header_file(configs, template_dir): + return False + if not self._generate_source_file(configs, template_dir): + return False + self._save_config(configs) + return True + + def _generate_header_file(self, configs, template_dir): + template_path = os.path.join(template_dir, "pwm.h") + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + + # 生成枚举 + enum_lines = [] + for config in configs: + enum_lines.append(f" BSP_PWM_{config['custom_name']},") + + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED BSP_PWM_ENUM", "\n".join(enum_lines) + ) + + output_path = os.path.join(self.project_path, "User/bsp/pwm.h") + save_with_preserve(output_path, content) + return True + + def _generate_source_file(self, configs, template_dir): + template_path = os.path.join(template_dir, "pwm.c") + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + + # 生成MAP数组 + map_lines = [] + for config in configs: + timer = config['timer'].lower() # tim1 -> htim1 + channel = config['channel'] + map_lines.append(f" {{&h{timer}, {channel}}},") + + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED BSP_PWM_MAP", "\n".join(map_lines) + ) + + output_path = os.path.join(self.project_path, "User/bsp/pwm.c") + save_with_preserve(output_path, content) + return True + + def _save_config(self, configs): + config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml") + config_data = CodeGenerator.load_config(config_path) + config_data['pwm'] = { + 'enabled': True, + 'configs': [ + { + 'custom_name': config['custom_name'], + 'timer': config['timer'], + 'channel': config['channel'], + 'label': config['label'] + } for config in configs + ] + } + CodeGenerator.save_config(config_data, config_path) + + def _load_config(self): + config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml") + config_data = CodeGenerator.load_config(config_path) + conf = config_data.get('pwm', {}) + if conf.get('enabled', False): + self.generate_checkbox.setChecked(True) + saved_configs = conf.get('configs', []) + # 恢复用户的自定义名称和选择状态 + for saved_config in saved_configs: + for row in range(len(self.available_list)): + if (self.available_list[row]['label'] == saved_config['label'] and + hasattr(self, 'table')): + name_widget = self.table.cellWidget(row, 1) + if name_widget: + name_widget.setText(saved_config['custom_name']) + +# 更新get_bsp_page函数以包含PWM def get_bsp_page(peripheral_name, project_path): """根据外设名返回对应的页面类,没有特殊类则返回默认BspSimplePeripheral""" name_lower = peripheral_name.lower() @@ -529,6 +942,7 @@ def get_bsp_page(peripheral_name, project_path): "spi": bsp_spi, "uart": bsp_uart, "gpio": bsp_gpio, + "pwm": bsp_pwm, # 添加PWM # 以后可以继续添加特殊外设 } if name_lower in special_classes: @@ -539,7 +953,8 @@ def get_bsp_page(peripheral_name, project_path): 'source': f'{name_lower}.c' } return BspSimplePeripheral(project_path, peripheral_name, template_names) - + + class bsp(QWidget): def __init__(self, project_path): super().__init__() diff --git a/app/tools/analyzing_ioc.py b/app/tools/analyzing_ioc.py index c92517a..6a85c3d 100644 --- a/app/tools/analyzing_ioc.py +++ b/app/tools/analyzing_ioc.py @@ -113,13 +113,15 @@ class analyzing_ioc: enabled_uart.append(uart_name) return sorted(enabled_uart) + @staticmethod def get_enabled_gpio_from_ioc(ioc_path): """ - 获取所有带 EXTI 且有 Label 的 GPIO,返回 [{'pin': 'PC4', 'label': 'ACCL_INT'}, ...] + 获取所有带 EXTI 且有 Label 的 GPIO,排除其他外设功能的引脚 """ gpio_list = [] - gpio_params = {} + gpio_configs = {} + with open(ioc_path, encoding='utf-8', errors='ignore') as f: for line in f: line = line.strip() @@ -129,18 +131,191 @@ class analyzing_ioc: key, value = line.split('=', 1) key = key.strip() value = value.strip() - if '.GPIOParameters' in key: - gpio_params[key.split('.')[0]] = value - elif '.GPIO_Label' in key: + + # 收集GPIO相关配置 + if '.' in key: pin = key.split('.')[0] - gpio_params[f"{pin}_label"] = value - elif '.GPIO_ModeDefaultEXTI' in key: + param = key.split('.', 1)[1] + + if pin not in gpio_configs: + gpio_configs[pin] = {} + + gpio_configs[pin][param] = value + + # 定义需要排除的Signal类型 + excluded_signals = [ + 'SPI1_SCK', 'SPI1_MISO', 'SPI1_MOSI', 'SPI2_SCK', 'SPI2_MISO', 'SPI2_MOSI', + 'SPI3_SCK', 'SPI3_MISO', 'SPI3_MOSI', + 'I2C1_SCL', 'I2C1_SDA', 'I2C2_SCL', 'I2C2_SDA', 'I2C3_SCL', 'I2C3_SDA', + 'USART1_TX', 'USART1_RX', 'USART2_TX', 'USART2_RX', 'USART3_TX', 'USART3_RX', + 'USART6_TX', 'USART6_RX', 'UART4_TX', 'UART4_RX', 'UART5_TX', 'UART5_RX', + 'CAN1_TX', 'CAN1_RX', 'CAN2_TX', 'CAN2_RX', + 'USB_OTG_FS_DM', 'USB_OTG_FS_DP', 'USB_OTG_HS_DM', 'USB_OTG_HS_DP', + 'SYS_JTMS-SWDIO', 'SYS_JTCK-SWCLK', 'SYS_JTDI', 'SYS_JTDO-SWO', + 'RCC_OSC_IN', 'RCC_OSC_OUT', + ] + + # 处理每个GPIO配置,只选择EXTI类型的 + for pin, config in gpio_configs.items(): + signal = config.get('Signal', '') + + # 只处理有Label和EXTI功能的GPIO + if ('GPIO_Label' not in config or + ('GPIO_ModeDefaultEXTI' not in config and not signal.startswith('GPXTI'))): + continue + + # 排除用于其他外设功能的引脚 + if signal in excluded_signals or signal.startswith('S_TIM') or signal.startswith('ADC'): + continue + + # 只包含EXTI功能的GPIO + if signal.startswith('GPXTI'): + label = config['GPIO_Label'] + gpio_list.append({'pin': pin, 'label': label}) + + return gpio_list + + + + @staticmethod + def get_all_gpio_from_ioc(ioc_path): + """ + 获取所有GPIO配置,但排除用于其他外设功能的引脚 + 只包含纯GPIO功能:GPIO_Input, GPIO_Output, GPXTI + """ + gpio_list = [] + gpio_configs = {} + + with open(ioc_path, encoding='utf-8', errors='ignore') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + if '=' in line: + key, value = line.split('=', 1) + key = key.strip() + value = value.strip() + + # 收集GPIO相关配置 + if '.' in key: pin = key.split('.')[0] - gpio_params[f"{pin}_exti"] = value - for pin in gpio_params: - if not pin.endswith('_label') and not pin.endswith('_exti'): - label = gpio_params.get(f"{pin}_label", None) - exti = gpio_params.get(f"{pin}_exti", None) - if label and exti: - gpio_list.append({'pin': pin, 'label': label}) - return gpio_list \ No newline at end of file + param = key.split('.', 1)[1] + + if pin not in gpio_configs: + gpio_configs[pin] = {} + + gpio_configs[pin][param] = value + + # 定义需要排除的Signal类型(用于其他外设功能的) + excluded_signals = [ + # SPI相关 + 'SPI1_SCK', 'SPI1_MISO', 'SPI1_MOSI', 'SPI2_SCK', 'SPI2_MISO', 'SPI2_MOSI', + 'SPI3_SCK', 'SPI3_MISO', 'SPI3_MOSI', + # I2C相关 + 'I2C1_SCL', 'I2C1_SDA', 'I2C2_SCL', 'I2C2_SDA', 'I2C3_SCL', 'I2C3_SDA', + # UART/USART相关 + 'USART1_TX', 'USART1_RX', 'USART2_TX', 'USART2_RX', 'USART3_TX', 'USART3_RX', + 'USART6_TX', 'USART6_RX', 'UART4_TX', 'UART4_RX', 'UART5_TX', 'UART5_RX', + # CAN相关 + 'CAN1_TX', 'CAN1_RX', 'CAN2_TX', 'CAN2_RX', + # USB相关 + 'USB_OTG_FS_DM', 'USB_OTG_FS_DP', 'USB_OTG_HS_DM', 'USB_OTG_HS_DP', + # 系统相关 + 'SYS_JTMS-SWDIO', 'SYS_JTCK-SWCLK', 'SYS_JTDI', 'SYS_JTDO-SWO', + 'RCC_OSC_IN', 'RCC_OSC_OUT', + ] + + # 处理每个GPIO配置 + for pin, config in gpio_configs.items(): + signal = config.get('Signal', '') + + # 只处理有Label的GPIO + if 'GPIO_Label' not in config: + continue + + # 排除用于其他外设功能的引脚 + if signal in excluded_signals: + continue + + # 排除TIM相关的引脚(以S_TIM开头的信号) + if signal.startswith('S_TIM'): + continue + + # 排除ADC相关的引脚 + if signal.startswith('ADC'): + continue + + # 只包含纯GPIO功能 + if signal in ['GPIO_Input', 'GPIO_Output'] or signal.startswith('GPXTI'): + gpio_info = { + 'pin': pin, + 'label': config['GPIO_Label'], + 'has_exti': 'GPIO_ModeDefaultEXTI' in config or signal.startswith('GPXTI'), + 'signal': signal, + 'mode': config.get('GPIO_ModeDefaultEXTI', ''), + 'is_output': signal == 'GPIO_Output', + 'is_input': signal == 'GPIO_Input' + } + gpio_list.append(gpio_info) + + return gpio_list + + @staticmethod + def get_enabled_pwm_from_ioc(ioc_path): + """ + 获取已启用的PWM通道列表 + 返回格式: [{'timer': 'TIM1', 'channel': 'TIM_CHANNEL_1', 'label': 'PWM_MOTOR1'}, ...] + """ + pwm_channels = [] + gpio_configs = {} + + with open(ioc_path, encoding='utf-8', errors='ignore') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + if '=' in line: + key, value = line.split('=', 1) + key = key.strip() + value = value.strip() + + # 收集GPIO相关配置 + if '.' in key: + pin = key.split('.')[0] + param = key.split('.', 1)[1] + + if pin not in gpio_configs: + gpio_configs[pin] = {} + + gpio_configs[pin][param] = value + + # 处理每个GPIO配置,查找PWM信号 + for pin, config in gpio_configs.items(): + signal = config.get('Signal', '') + + # 检查是否为PWM信号(格式如:S_TIM1_CH1, S_TIM2_CH3等) + if signal.startswith('S_TIM') and '_CH' in signal: + # 解析定时器和通道信息 + # 例如:S_TIM1_CH1 -> TIM1, CH1 + parts = signal.replace('S_', '').split('_') + if len(parts) >= 2: + timer = parts[0] # TIM1 + channel_part = parts[1] # CH1 + + # 转换通道格式:CH1 -> TIM_CHANNEL_1 + if channel_part.startswith('CH'): + channel_num = channel_part[2:] # 提取数字 + channel = f"TIM_CHANNEL_{channel_num}" + + # 获取标签 + label = config.get('GPIO_Label', f"{timer}_{channel_part}") + + pwm_channels.append({ + 'timer': timer, + 'channel': channel, + 'label': label, + 'pin': pin, + 'signal': signal + }) + + return pwm_channels \ No newline at end of file diff --git a/assets/User_code/bsp/.DS_Store b/assets/User_code/bsp/.DS_Store index dc0ff54..ec9a612 100644 Binary files a/assets/User_code/bsp/.DS_Store and b/assets/User_code/bsp/.DS_Store differ diff --git a/assets/User_code/bsp/can.c b/assets/User_code/bsp/can.c index f887116..98acb19 100644 --- a/assets/User_code/bsp/can.c +++ b/assets/User_code/bsp/can.c @@ -1,19 +1,106 @@ /* Includes ----------------------------------------------------------------- */ -#include "bsp\can.h" +#include "bsp/can.h" +#include "bsp/bsp.h" +#include +#include +#include +#include /* Private define ----------------------------------------------------------- */ + /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ +typedef struct CAN_QueueNode { + uint32_t can_id; + osMessageQueueId_t queue; + uint8_t queue_size; + struct CAN_QueueNode *next; +} CAN_QueueNode_t; + /* Private variables -------------------------------------------------------- */ +static CAN_QueueNode_t *can_queue_list = NULL; static void (*CAN_Callback[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void); +/* Private function prototypes ---------------------------------------------- */ +static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan); +static osMessageQueueId_t find_queue(uint32_t can_id); +static void can_rx_fifo0_handler(void); +static void can_rx_fifo1_handler(void); + +/* AUTO GENERATED CAN_RX_CALLBACKS */ /* Private function -------------------------------------------------------- */ + +/* 查找指定CAN ID的队列 */ +static osMessageQueueId_t find_queue(uint32_t can_id) { + CAN_QueueNode_t *node = can_queue_list; + while (node) { + if (node->can_id == can_id) return node->queue; + node = node->next; + } + return NULL; +} + +/* FIFO0接收处理函数 */ +static void can_rx_fifo0_handler(void) { + CAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[8]; + + // 遍历所有CAN接口处理FIFO0 + for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { + CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle((BSP_CAN_t)can_idx); + if (hcan == NULL) continue; + + while (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) > 0) { + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) == HAL_OK) { + uint32_t can_id = (rx_header.IDE == CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId; + osMessageQueueId_t queue = find_queue(can_id); + if (queue) { + CAN_Message_t msg; + msg.header = rx_header; + memcpy(msg.data, rx_data, 8); + // 非阻塞发送,如果队列满了就丢弃 + osMessageQueuePut(queue, &msg, 0, 0); + } + // 如果没有找到对应的队列,消息被直接丢弃 + } + } + } +} + +/* FIFO1接收处理函数 */ +static void can_rx_fifo1_handler(void) { + CAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[8]; + + // 遍历所有CAN接口处理FIFO1 + for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { + CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle((BSP_CAN_t)can_idx); + if (hcan == NULL) continue; + + while (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO1) > 0) { + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &rx_header, rx_data) == HAL_OK) { + uint32_t can_id = (rx_header.IDE == CAN_ID_STD) ? rx_header.StdId : rx_header.ExtId; + osMessageQueueId_t queue = find_queue(can_id); + if (queue) { + CAN_Message_t msg; + msg.header = rx_header; + memcpy(msg.data, rx_data, 8); + // 非阻塞发送,如果队列满了就丢弃 + osMessageQueuePut(queue, &msg, 0, 0); + } + // 如果没有找到对应的队列,消息被直接丢弃 + } + } + } +} + static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan) { /* AUTO GENERATED CAN_GET */ else return BSP_CAN_ERR; } +/* HAL Callback Functions --------------------------------------------------- */ void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { BSP_CAN_t bsp_can = CAN_Get(hcan); if (bsp_can != BSP_CAN_ERR) { @@ -130,6 +217,132 @@ CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can) { int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type, void (*callback)(void)) { if (callback == NULL) return BSP_ERR_NULL; + if (can >= BSP_CAN_NUM) return BSP_ERR_INITED; + if (type >= BSP_CAN_CB_NUM) return BSP_ERR; + CAN_Callback[can][type] = callback; return BSP_OK; } + +int BSP_CAN_GetMessage(uint32_t can_id, CAN_Message_t *msg, uint32_t timeout) { + if (msg == NULL) return BSP_ERR_NULL; + osMessageQueueId_t queue = find_queue(can_id); + if (!queue) return BSP_ERR_NO_DEV; // 没有该队列 + if (osMessageQueueGet(queue, msg, NULL, timeout) == osOK) { + return BSP_OK; // 成功 + } + return BSP_ERR; // 超时或队列为空 +} + +int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size) { + // 检查是否已存在 + CAN_QueueNode_t *node = can_queue_list; + while (node) { + if (node->can_id == can_id) { + return BSP_ERR; // 已存在 + } + node = node->next; + } + // 创建新节点 + CAN_QueueNode_t *new_node = malloc(sizeof(CAN_QueueNode_t)); + if (new_node == NULL) return BSP_ERR_NULL; + new_node->can_id = can_id; + new_node->queue_size = queue_size; + new_node->queue = osMessageQueueNew(queue_size, sizeof(CAN_Message_t), NULL); + if (new_node->queue == NULL) { + free(new_node); + return BSP_ERR; + } + new_node->next = can_queue_list; + can_queue_list = new_node; + return BSP_OK; +} + + +int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id) { + CAN_QueueNode_t **current = &can_queue_list; + while (*current) { + if ((*current)->can_id == can_id) { + CAN_QueueNode_t *to_delete = *current; + *current = (*current)->next; + osMessageQueueDelete(to_delete->queue); + free(to_delete); + return BSP_OK; + } + current = &(*current)->next; + } + return BSP_ERR; // 未找到 +} + + +void BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size) { + BSP_CAN_CreateIdQueue(can_id, queue_size); +} + + +int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, + uint32_t id, uint8_t *data, uint8_t dlc) { + if (can >= BSP_CAN_NUM) return BSP_ERR; + if (data == NULL) return BSP_ERR_NULL; + if (dlc > 8) return BSP_ERR; + + CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can); + if (hcan == NULL) return BSP_ERR_NULL; + + CAN_TxHeaderTypeDef header; + uint32_t mailbox; + + switch (format) { + case CAN_FORMAT_STD_DATA: + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_DATA; + header.TransmitGlobalTime = DISABLE; + header.DLC = dlc; + break; + case CAN_FORMAT_EXT_DATA: + header.ExtId = id; + header.IDE = CAN_ID_EXT; + header.RTR = CAN_RTR_DATA; + header.TransmitGlobalTime = DISABLE; + header.DLC = dlc; + break; + case CAN_FORMAT_STD_REMOTE: + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_REMOTE; + header.TransmitGlobalTime = DISABLE; + header.DLC = dlc; + break; + case CAN_FORMAT_EXT_REMOTE: + header.ExtId = id; + header.IDE = CAN_ID_EXT; + header.RTR = CAN_RTR_REMOTE; + header.TransmitGlobalTime = DISABLE; + header.DLC = dlc; + break; + default: + return BSP_ERR; + } + + HAL_StatusTypeDef res = HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); + + if (res == HAL_OK) { + return BSP_OK; + } else { + return BSP_ERR; + } +} + +int8_t BSP_CAN_Init(void) { +/* AUTO GENERATED CAN_INIT */ + + // 注册接收中断处理函数 + for (int can_idx = 0; can_idx < BSP_CAN_NUM; can_idx++) { + BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, can_rx_fifo0_handler); + BSP_CAN_RegisterCallback((BSP_CAN_t)can_idx, HAL_CAN_RX_FIFO1_MSG_PENDING_CB, can_rx_fifo1_handler); + } + + return BSP_OK; +} + diff --git a/assets/User_code/bsp/can.h b/assets/User_code/bsp/can.h index 4cfe168..709d37c 100644 --- a/assets/User_code/bsp/can.h +++ b/assets/User_code/bsp/can.h @@ -6,10 +6,14 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include - #include "bsp/bsp.h" +#include +#include +#include /* Exported constants ------------------------------------------------------- */ + + /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ typedef enum { @@ -35,11 +39,85 @@ typedef enum { BSP_CAN_CB_NUM } BSP_CAN_Callback_t; +typedef enum { + CAN_FORMAT_STD_DATA, /* 标准数据帧 */ + CAN_FORMAT_EXT_DATA, /* 扩展数据帧 */ + CAN_FORMAT_STD_REMOTE, /* 标准远程帧 */ + CAN_FORMAT_EXT_REMOTE, /* 扩展远程帧 */ +} BSP_CAN_Format_t; + +typedef struct { + CAN_RxHeaderTypeDef header; + uint8_t data[8]; +} CAN_Message_t; + /* Exported functions prototypes -------------------------------------------- */ +/** + * @brief 获取 CAN 句柄 + * @param can CAN 枚举类型 + * @return CAN_HandleTypeDef 指针,失败返回 NULL + */ CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can); + +/** + * @brief 注册 CAN 回调 + * @param can CAN 枚举类型 + * @param type 回调类型 + * @param callback 回调函数指针 + * @return BSP_OK 成功,BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + */ int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type, void (*callback)(void)); -#ifdef __cplusplus -} -#endif +/** + * @brief 发送 CAN 消息 + * @param can CAN 枚举类型 + * @param format 消息格式 + * @param id CAN ID + * @param data 数据指针 + * @param dlc 数据长度 + * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + */ +int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, + uint32_t id, uint8_t *data, uint8_t dlc); + +/** + * @brief 初始化 CAN + * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INITED 失败 + */ +int8_t BSP_CAN_Init(void); + +/** + * @brief 获取 CAN 消息 + * @param can_id CAN ID + * @param msg 存储消息的结构体指针 + * @param timeout 超时时间(毫秒) + * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_NO_DEV 失败 + */ +int BSP_CAN_GetMessage(uint32_t can_id, CAN_Message_t *msg, uint32_t timeout); + +/** + * @brief 注册 CAN ID + * @param can_id CAN ID + * @param queue_size 队列大小 + * @return 无 + */ +void BSP_CAN_RegisterId(uint32_t can_id, uint8_t queue_size); + +/** + * @brief 创建指定 CAN ID 的队列 + * @param can_id CAN ID + * @param queue_size 队列大小 + * @return BSP_OK 成功,BSP_ERR/BSP_ERR_NULL/BSP_ERR_INVALID_PARAM 失败 + */ +int8_t BSP_CAN_CreateIdQueue(uint32_t can_id, uint8_t queue_size); + +/** + * @brief 删除指定 CAN ID 的队列 + * @param can_id CAN ID + * @return BSP_OK 成功,BSP_ERR/BSP_ERR_INVALID_PARAM 失败 + */ +int8_t BSP_CAN_DeleteIdQueue(uint32_t can_id); + +/* USER CAN FUNCTIONS BEGIN */ +/* USER CAN FUNCTIONS END */ \ No newline at end of file diff --git a/assets/User_code/bsp/describe.csv b/assets/User_code/bsp/describe.csv index 620500e..25a5f06 100644 --- a/assets/User_code/bsp/describe.csv +++ b/assets/User_code/bsp/describe.csv @@ -3,4 +3,5 @@ can,要求开启can的中断要求开启can的中断要求开启can的中断要 gpio,要求设置label开启中断 spi,要求开启spi中断 i2c,要求开始spi中断 -mm,这是套了一层的内存 \ No newline at end of file +mm,这是套了一层的内存 +time,需要使用开启freerots \ No newline at end of file diff --git a/assets/User_code/bsp/gpio.c b/assets/User_code/bsp/gpio.c index 19fd446..da3a24c 100644 --- a/assets/User_code/bsp/gpio.c +++ b/assets/User_code/bsp/gpio.c @@ -7,7 +7,16 @@ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ +typedef struct { + uint16_t pin; + GPIO_TypeDef *gpio; +} BSP_GPIO_MAP_t; + /* Private variables -------------------------------------------------------- */ +static const BSP_GPIO_MAP_t GPIO_Map[BSP_GPIO_NUM] = { +/* AUTO GENERATED BSP_GPIO_MAP */ +}; + static void (*GPIO_Callback[16])(void); /* Private function -------------------------------------------------------- */ @@ -36,7 +45,7 @@ int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)) { int8_t BSP_GPIO_EnableIRQ(uint16_t pin) { switch (pin) { - /* AUTO GENERATED BSP_GPIO_ENABLE_IRQ */ +/* AUTO GENERATED BSP_GPIO_ENABLE_IRQ */ default: return BSP_ERR; } @@ -45,9 +54,26 @@ int8_t BSP_GPIO_EnableIRQ(uint16_t pin) { int8_t BSP_GPIO_DisableIRQ(uint16_t pin) { switch (pin) { - /* AUTO GENERATED BSP_GPIO_DISABLE_IRQ */ +/* AUTO GENERATED BSP_GPIO_DISABLE_IRQ */ default: return BSP_ERR; } return BSP_OK; +} + +int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value){ + if (gpio >= BSP_GPIO_NUM) return BSP_ERR; + HAL_GPIO_WritePin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin, value); + return BSP_OK; +} + +int8_t BSP_GPIO_TogglePin(BSP_GPIO_t gpio){ + if (gpio >= BSP_GPIO_NUM) return BSP_ERR; + HAL_GPIO_TogglePin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin); + return BSP_OK; +} + +bool BSP_GPIO_ReadPin(BSP_GPIO_t gpio){ + if (gpio >= BSP_GPIO_NUM) return false; + return HAL_GPIO_ReadPin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin) == GPIO_PIN_SET; } \ No newline at end of file diff --git a/assets/User_code/bsp/gpio.h b/assets/User_code/bsp/gpio.h index d2eeae8..a11d717 100644 --- a/assets/User_code/bsp/gpio.h +++ b/assets/User_code/bsp/gpio.h @@ -6,18 +6,30 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include +#include #include "bsp/bsp.h" /* Exported constants ------------------------------------------------------- */ /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ +typedef enum { +/* AUTO GENERATED BSP_GPIO_ENUM */ + BSP_GPIO_NUM, + BSP_GPIO_ERR, +} BSP_GPIO_t; + /* Exported functions prototypes -------------------------------------------- */ int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)); int8_t BSP_GPIO_EnableIRQ(uint16_t pin); int8_t BSP_GPIO_DisableIRQ(uint16_t pin); +int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value); +int8_t BSP_GPIO_TogglePin(BSP_GPIO_t gpio); + +bool BSP_GPIO_ReadPin(BSP_GPIO_t gpio); + #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/assets/User_code/bsp/i2c.c b/assets/User_code/bsp/i2c.c index de66db3..12c7539 100644 --- a/assets/User_code/bsp/i2c.c +++ b/assets/User_code/bsp/i2c.c @@ -101,3 +101,76 @@ int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type, I2C_Callback[i2c][type] = callback; return BSP_OK; } + +int8_t BSP_I2C_Transmit(BSP_I2C_t i2c, uint16_t devAddr, uint8_t *data, + uint16_t size, bool dma) { + if (i2c >= BSP_I2C_NUM) return BSP_ERR; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return BSP_ERR; + + if (dma) { + return HAL_I2C_Master_Transmit_DMA(hi2c, devAddr, data, size); + } else { + return HAL_I2C_Master_Transmit_IT(hi2c, devAddr, data, size); + } +} + +int8_t BSP_I2C_Receive(BSP_I2C_t i2c, uint16_t devAddr, uint8_t *data, + uint16_t size, bool dma) { + if (i2c >= BSP_I2C_NUM) return BSP_ERR; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return BSP_ERR; + + if (dma) { + return HAL_I2C_Master_Receive_DMA(hi2c, devAddr, data, size); + } else { + return HAL_I2C_Master_Receive_IT(hi2c, devAddr, data, size); + } +} + +uint8_t BSP_I2C_MemReadByte(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr) { + if (i2c >= BSP_I2C_NUM) return 0xFF; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return 0xFF; + + uint8_t data; + HAL_I2C_Mem_Read(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, &data, 1, HAL_MAX_DELAY); + return data; +} + +int8_t BSP_I2C_MemWriteByte(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t data) { + if (i2c >= BSP_I2C_NUM) return BSP_ERR; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return BSP_ERR; + + return HAL_I2C_Mem_Write(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, &data, 1, HAL_MAX_DELAY); +} + +int8_t BSP_I2C_MemRead(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t *data, uint16_t size, bool dma) { + if (i2c >= BSP_I2C_NUM || data == NULL || size == 0) return BSP_ERR; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return BSP_ERR; + + if (dma) { + return HAL_I2C_Mem_Read_DMA(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, data, size); + } + else { + return HAL_I2C_Mem_Read(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, data, size, HAL_MAX_DELAY); + } +} + + +int8_t BSP_I2C_MemWrite(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t *data, uint16_t size, bool dma) { + if (i2c >= BSP_I2C_NUM || data == NULL || size == 0) return BSP_ERR; + I2C_HandleTypeDef *hi2c = BSP_I2C_GetHandle(i2c); + if (hi2c == NULL) return BSP_ERR; + + if (dma) { + return HAL_I2C_Mem_Write_DMA(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, data, size); + } else { + return HAL_I2C_Mem_Write(hi2c, devAddr, memAddr, I2C_MEMADD_SIZE_16BIT, data, size, HAL_MAX_DELAY); + } +} \ No newline at end of file diff --git a/assets/User_code/bsp/i2c.h b/assets/User_code/bsp/i2c.h index fecb246..ab75d48 100644 --- a/assets/User_code/bsp/i2c.h +++ b/assets/User_code/bsp/i2c.h @@ -6,6 +6,8 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include +#include +#include #include "bsp/bsp.h" @@ -44,6 +46,22 @@ I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c); int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type, void (*callback)(void)); +int8_t BSP_I2C_Transmit(BSP_I2C_t i2c, uint16_t devAddr, uint8_t *data, + uint16_t size, bool dma); +int8_t BSP_I2C_Receive(BSP_I2C_t i2c, uint16_t devAddr, uint8_t *data, + uint16_t size, bool dma); + + +uint8_t BSP_I2C_MemReadByte(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr); +int8_t BSP_I2C_MemWriteByte(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t data); + +int8_t BSP_I2C_MemRead(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t *data, uint16_t size, bool dma); +int8_t BSP_I2C_MemWrite(BSP_I2C_t i2c, uint16_t devAddr, uint16_t memAddr, + uint8_t *data, uint16_t size, bool dma); + + #ifdef __cplusplus } #endif diff --git a/assets/User_code/bsp/pwm.c b/assets/User_code/bsp/pwm.c new file mode 100644 index 0000000..550d7a4 --- /dev/null +++ b/assets/User_code/bsp/pwm.c @@ -0,0 +1,70 @@ +/* Includes ----------------------------------------------------------------- */ +#include "bsp/pwm.h" +#include "bsp.h" + +#include + +/* Private define ----------------------------------------------------------- */ +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +typedef struct { + TIM_HandleTypeDef *tim; + uint16_t channel; +} BSP_PWM_Config_t; + +/* Private variables -------------------------------------------------------- */ +static const BSP_PWM_Config_t PWM_Map[BSP_PWM_NUM] = { +/* AUTO GENERATED BSP_PWM_MAP */ +}; + +/* Private function -------------------------------------------------------- */ +/* Exported functions ------------------------------------------------------- */ + +int8_t BSP_PWM_Start(BSP_PWM_Channel_t ch) { + if (ch >= BSP_PWM_NUM) return BSP_ERR; + + HAL_TIM_PWM_Start(PWM_Map[ch].tim, PWM_Map[ch].channel); + return BSP_OK; +} + +int8_t BSP_PWM_SetComp(BSP_PWM_Channel_t ch, float duty_cycle) { + if (ch >= BSP_PWM_NUM) return BSP_ERR; + + if (duty_cycle > 1.0f) { + duty_cycle = 1.0f; + } + if (duty_cycle < 0.0f) { + duty_cycle = 0.0f; + } + + // 获取ARR值(周期值) + uint32_t arr = __HAL_TIM_GET_AUTORELOAD(PWM_Map[ch].tim); + + // 计算比较值:CCR = duty_cycle * (ARR + 1) + uint32_t ccr = (uint32_t)(duty_cycle * (arr + 1)); + + __HAL_TIM_SET_COMPARE(PWM_Map[ch].tim, PWM_Map[ch].channel, ccr); + return BSP_OK; +} + +int8_t BSP_PWM_SetFreq(BSP_PWM_Channel_t ch, float freq) { + if (ch >= BSP_PWM_NUM) return BSP_ERR; + + uint32_t timer_clock = HAL_RCC_GetPCLK1Freq(); // Get the timer clock frequency + uint32_t prescaler = PWM_Map[ch].tim->Init.Prescaler; + uint32_t period = (timer_clock / (prescaler + 1)) / freq - 1; + + if (period > UINT16_MAX) { + return BSP_ERR; // Frequency too low + } + __HAL_TIM_SET_AUTORELOAD(PWM_Map[ch].tim, period); + + return BSP_OK; +} + +int8_t BSP_PWM_Stop(BSP_PWM_Channel_t ch) { + if (ch >= BSP_PWM_NUM) return BSP_ERR; + + HAL_TIM_PWM_Stop(PWM_Map[ch].tim, PWM_Map[ch].channel); + return BSP_OK; +} \ No newline at end of file diff --git a/assets/User_code/bsp/pwm.h b/assets/User_code/bsp/pwm.h new file mode 100644 index 0000000..03f6cf5 --- /dev/null +++ b/assets/User_code/bsp/pwm.h @@ -0,0 +1,30 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include + +#include "bsp.h" + +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +/* PWM通道 */ +typedef enum { +/* AUTO GENERATED BSP_PWM_ENUM */ + BSP_PWM_NUM, + BSP_PWM_ERR, +} BSP_PWM_Channel_t; + +/* Exported functions prototypes -------------------------------------------- */ +int8_t BSP_PWM_Start(BSP_PWM_Channel_t ch); +int8_t BSP_PWM_SetComp(BSP_PWM_Channel_t ch, float duty_cycle); +int8_t BSP_PWM_SetFreq(BSP_PWM_Channel_t ch, float freq); +int8_t BSP_PWM_Stop(BSP_PWM_Channel_t ch); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/assets/User_code/bsp/spi.c b/assets/User_code/bsp/spi.c index 7560f3f..5226feb 100644 --- a/assets/User_code/bsp/spi.c +++ b/assets/User_code/bsp/spi.c @@ -94,3 +94,74 @@ int8_t BSP_SPI_RegisterCallback(BSP_SPI_t spi, BSP_SPI_Callback_t type, SPI_Callback[spi][type] = callback; return BSP_OK; } + +int8_t BSP_SPI_Transmit(BSP_SPI_t spi, uint8_t *data, uint16_t size, bool dma) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL) return BSP_ERR; + + if (dma) { + return HAL_SPI_Transmit_DMA(hspi, data, size); + } else { + return HAL_SPI_Transmit_IT(hspi, data, size); + } +} + +int8_t BSP_SPI_Receive(BSP_SPI_t spi, uint8_t *data, uint16_t size, bool dma) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL) return BSP_ERR; + + if (dma) { + return HAL_SPI_Receive_DMA(hspi, data, size); + } else { + return HAL_SPI_Receive_IT(hspi, data, size); + } +} + +int8_t BSP_SPI_TransmitReceive(BSP_SPI_t spi, uint8_t *txData, uint8_t *rxData, + uint16_t size, bool dma) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL) return BSP_ERR; + + if (dma) { + return HAL_SPI_TransmitReceive_DMA(hspi, txData, rxData, size); + } else { + return HAL_SPI_TransmitReceive_IT(hspi, txData, rxData, size); + } +} + +uint8_t BSP_SPI_MemReadByte(BSP_SPI_t spi, uint8_t reg) { + if (spi >= BSP_SPI_NUM) return 0xFF; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL) return 0xFF; + + uint8_t data = 0; + HAL_SPI_Mem_Read(hspi, reg, &data, sizeof(data)); + return data; +} + +int8_t BSP_SPI_MemWriteByte(BSP_SPI_t spi, uint8_t reg, uint8_t data) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL) return BSP_ERR; + + return HAL_SPI_Mem_Write(hspi, reg, &data, sizeof(data)); +} + +int8_t BSP_SPI_MemRead(BSP_SPI_t spi, uint8_t reg, uint8_t *data, uint16_t size) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL || data == NULL || size == 0) return BSP_ERR_NULL; + + return HAL_SPI_Mem_Read(hspi, reg, data, size); +} + +int8_t BSP_SPI_MemWrite(BSP_SPI_t spi, uint8_t reg, uint8_t *data, uint16_t size) { + if (spi >= BSP_SPI_NUM) return BSP_ERR; + SPI_HandleTypeDef *hspi = BSP_SPI_GetHandle(spi); + if (hspi == NULL || data == NULL || size == 0) return BSP_ERR_NULL; + + return HAL_SPI_Mem_Write(hspi, reg, data, size); +} diff --git a/assets/User_code/bsp/spi.h b/assets/User_code/bsp/spi.h index e42bab7..a4d0ea7 100644 --- a/assets/User_code/bsp/spi.h +++ b/assets/User_code/bsp/spi.h @@ -6,6 +6,7 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include +#include #include "bsp/bsp.h" @@ -40,6 +41,17 @@ SPI_HandleTypeDef *BSP_SPI_GetHandle(BSP_SPI_t spi); int8_t BSP_SPI_RegisterCallback(BSP_SPI_t spi, BSP_SPI_Callback_t type, void (*callback)(void)); + +int8_t BSP_SPI_Transmit(BSP_SPI_t spi, uint8_t *data, uint16_t size, bool dma); +int8_t BSP_SPI_Receive(BSP_SPI_t spi, uint8_t *data, uint16_t size, bool dma); +int8_t BSP_SPI_TransmitReceive(BSP_SPI_t spi, uint8_t *txData, uint8_t *rxData, + uint16_t size, bool dma); + +uint8_t BSP_SPI_MemReadByte(BSP_SPI_t spi, uint8_t reg); +int8_t BSP_SPI_MemWriteByte(BSP_SPI_t spi, uint8_t reg, uint8_t data); +int8_t BSP_SPI_MemRead(BSP_SPI_t spi, uint8_t reg, uint8_t *data, uint16_t size); +int8_t BSP_SPI_MemWrite(BSP_SPI_t spi, uint8_t reg, uint8_t *data, uint16_t size); + #ifdef __cplusplus } #endif diff --git a/assets/User_code/bsp/delay.c b/assets/User_code/bsp/time.c similarity index 53% rename from assets/User_code/bsp/delay.c rename to assets/User_code/bsp/time.c index d63fb61..0ea6087 100644 --- a/assets/User_code/bsp/delay.c +++ b/assets/User_code/bsp/time.c @@ -1,16 +1,35 @@ /* Includes ----------------------------------------------------------------- */ #include "bsp/delay.h" +#include "bsp.h" #include -#include - +#include "FreeRTOS.h" +#include "main.h" +#include "task.h" /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ /* Private variables -------------------------------------------------------- */ /* Private function -------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */ -int8_t BSP_Delay(uint32_t ms) { + +uint32_t BSP_TIME_Get_ms() { return xTaskGetTickCount(); } + +uint64_t BSP_TIME_Get_us() { + uint32_t ms_old = xTaskGetTickCount(); + uint32_t tick_value_old = SysTick->VAL; + uint32_t ms_new = xTaskGetTickCount(); + uint32_t tick_value_new = SysTick->VAL; + if (ms_old == ms_new) { + return ms_new * 1000 + 1000 - tick_value_old * 1000 / (SysTick->LOAD + 1); + } else { + return ms_new * 1000 + 1000 - tick_value_new * 1000 / (SysTick->LOAD + 1); + } +} + +uint64_t BSP_TIME_Get() __attribute__((alias("BSP_TIME_Get_us"))); + +int8_t BSP_TIME_Delay_ms(uint32_t ms) { uint32_t tick_period = 1000u / osKernelGetTickFreq(); uint32_t ticks = ms / tick_period; @@ -32,3 +51,14 @@ int8_t BSP_Delay(uint32_t ms) { } return BSP_OK; } + +/*阻塞us延迟*/ +int8_t BSP_TIME_Delay_us(uint32_t us) { + uint64_t start = BSP_TIME_Get_us(); + while (BSP_TIME_Get_us() - start < us) { + // 等待us时间 + } + return BSP_OK; +} + +int8_t BSP_TIME_Delay(uint32_t ms) __attribute__((alias("BSP_TIME_Delay_ms"))); \ No newline at end of file diff --git a/assets/User_code/bsp/delay.h b/assets/User_code/bsp/time.h similarity index 69% rename from assets/User_code/bsp/delay.h rename to assets/User_code/bsp/time.h index 82e730f..5273f0f 100644 --- a/assets/User_code/bsp/delay.h +++ b/assets/User_code/bsp/time.h @@ -13,7 +13,18 @@ extern "C" { /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ /* Exported functions prototypes -------------------------------------------- */ -int8_t BSP_Delay(uint32_t ms); +uint32_t BSP_TIME_Get_ms(); + +uint64_t BSP_TIME_Get_us(); + +uint64_t BSP_TIME_Get(); + +int8_t BSP_TIME_Delay_ms(uint32_t ms); + +/*微秒阻塞延时,一般别用*/ +int8_t BSP_TIME_Delay_us(uint32_t us); + +int8_t BSP_TIME_Delay(uint32_t ms); #ifdef __cplusplus } diff --git a/assets/User_code/bsp/uart.c b/assets/User_code/bsp/uart.c index 0fde9d0..d9a235d 100644 --- a/assets/User_code/bsp/uart.c +++ b/assets/User_code/bsp/uart.c @@ -1,5 +1,7 @@ /* Includes ----------------------------------------------------------------- */ -#include "bsp\uart.h" +#include + +#include "bsp/uart.h" /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ @@ -107,6 +109,29 @@ UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart) { int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type, void (*callback)(void)) { if (callback == NULL) return BSP_ERR_NULL; + if (uart >= BSP_UART_NUM || type >= BSP_UART_CB_NUM) return BSP_ERR; UART_Callback[uart][type] = callback; return BSP_OK; } + +int8_t BSP_UART_Transmit(BSP_UART_t uart, uint8_t *data, uint16_t size, bool dma) { + if (uart >= BSP_UART_NUM) return BSP_ERR; + if (data == NULL || size == 0) return BSP_ERR_NULL; + + if (dma) { + return HAL_UART_Transmit_DMA(BSP_UART_GetHandle(uart), data, size); + } else { + return HAL_UART_Transmit_IT(BSP_UART_GetHandle(uart), data, size); + } +} + +int8_t BSP_UART_Receive(BSP_UART_t uart, uint8_t *data, uint16_t size, bool dma) { + if (uart >= BSP_UART_NUM) return BSP_ERR; + if (data == NULL || size == 0) return BSP_ERR_NULL; + + if (dma) { + return HAL_UART_Receive_DMA(BSP_UART_GetHandle(uart), data, size); + } else { + return HAL_UART_Receive_IT(BSP_UART_GetHandle(uart), data, size); + } +} \ No newline at end of file diff --git a/assets/User_code/bsp/uart.h b/assets/User_code/bsp/uart.h index 1a0b795..bbb6126 100644 --- a/assets/User_code/bsp/uart.h +++ b/assets/User_code/bsp/uart.h @@ -6,6 +6,7 @@ extern "C" { /* Includes ----------------------------------------------------------------- */ #include +#include #include "bsp/bsp.h" @@ -38,9 +39,13 @@ typedef enum { } BSP_UART_Callback_t; /* Exported functions prototypes -------------------------------------------- */ + UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart); int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type, void (*callback)(void)); + +int8_t BSP_UART_Transmit(BSP_UART_t uart, uint8_t *data, uint16_t size, bool dma); +int8_t BSP_UART_Receive(BSP_UART_t uart, uint8_t *data, uint16_t size, bool dma); #ifdef __cplusplus } diff --git a/assets/User_code/config.csv b/assets/User_code/config.csv index 2aa03c1..bd8d5ac 100644 --- a/assets/User_code/config.csv +++ b/assets/User_code/config.csv @@ -1,4 +1,4 @@ -bsp,can,delay,dwt,,gpio,i2c,mm,spi,uart, +bsp,can,delay,dwt,,gpio,i2c,mm,spi,uart,pwm,time component,pid,filter,ahrs device,dr16,ai,nuc module,chassis,gimbal,arm,shoot \ No newline at end of file diff --git a/assets/User_code/device/.DS_Store b/assets/User_code/device/.DS_Store index 42ce4ca..1fc8ef0 100644 Binary files a/assets/User_code/device/.DS_Store and b/assets/User_code/device/.DS_Store differ diff --git a/assets/User_code/device/bmp280_i2c.c b/assets/User_code/device/bmp280_i2c.c deleted file mode 100644 index 1cac0f2..0000000 --- a/assets/User_code/device/bmp280_i2c.c +++ /dev/null @@ -1,301 +0,0 @@ -#include "bmp280_i2c.h" -#include "bsp/i2c.h" - -#define I2C_Handle BSP_I2C_GetHandle(BSP_I2C_BMP280) - -/** - * @brief 读寄存器 - * @param regAdd 寄存器开始地址 - * @param pdata 存储数据的指针 - * @param size 寄存器个数 - * @retval 无 - */ -void bmp280_readReg(uint8_t regAdd, uint8_t *pdata, uint8_t size) { - HAL_I2C_Mem_Read(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, size, 1000); -} - - - -/** - * @brief 写1个寄存器 - * @param regAdd 寄存器开始地址 - * @param pdata 存储数据的指针 - * @retval 0 写入成功 - * 1 写入失败 - */ -uint8_t bmp280_writeReg(uint8_t regAdd, uint8_t *pdata) { - if (HAL_I2C_Mem_Write(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, 1, 1000) == HAL_OK) { - return 0; - } - return 1; -} - - -/** - * @brief 读取设备物理id,用于调试 - * @param 无 - * @retval 设备id - */ -uint8_t bmp280_get_id(void) { - uint8_t temp = 0; - bmp280_readReg(BMP280_ID, &temp, 1); - return temp; -} - -/** - * @brief 重启设备 - * @param 无 - * @retval 0 重启成功 - * 1 重启失败 - */ -uint8_t bmp280_reset(void) { - uint8_t temp = 0xB6; - return bmp280_writeReg(BMP280_RESET, &temp); -} - -/** - * @brief 获取设备状态 - * @param 无 - * @retval 0 空闲 - * 1 正在测量或者正在复制 - */ -uint8_t bmp280_getStatus(void) { - uint8_t temp = 0; - bmp280_readReg(BMP280_STATUS, &temp, 1); - return (temp & 0x09) ? 1 : 0; -} - - - /** - * @brief 工作模式设置推荐 - * @param mode 0 睡眠模式 - * 1 单次测量模式,测量完成后回到休眠模式 - * 2 连续测量模式 - * @retval 0 设置成功 - * 1 设置失败 - */ -uint8_t bmp280_setMode(uint8_t mode) -{ - uint8_t temp=0; - bmp280_readReg(BMP280_CTRL_MEAS,&temp,1); - switch(mode) - { - case 0: - temp&=0xFC; - break; - case 1: - temp&=0xFC; - temp|=0x01; - break; - case 2: - temp&=0xFC; - temp|=0x03; - break; - default: - return 1; - } - return bmp280_writeReg(BMP280_CTRL_MEAS,&temp); -} - - - /** - * @brief 过采样设置 - * @param mode temp&press 0 禁用 - * 1 过采样×1 - * 2 过采样×2 - * 3 过采样×4 - * .. ..... - * 5 过采样×16 - * @retval 0 设置成功 - * 1 设置失败 - */ -uint8_t bmp280_setOversampling(uint8_t osrs_p,uint8_t osrs_t) -{ - uint8_t temp=0; - bmp280_readReg(BMP280_CTRL_MEAS,&temp,1); - temp&=0xE3; - osrs_p = osrs_p<<2; - osrs_p&= 0x1C; - temp|=osrs_p; - - temp&=0x1F; - osrs_t = osrs_t<<5; - osrs_t&= 0xE0; - temp|=osrs_t; - return bmp280_writeReg(BMP280_CTRL_MEAS,&temp); -} - - - /** - * @brief 滤波器系数和采样间隔时间设置 - * @param Standbyt 0 0.5ms filter 0 关闭滤波器 - * 1 62.5ms 1 2 - * 2 125ms 2 4 - * 3 250ms 3 8 - * 4 500ms 4 16 - * 5 1000ms - * 6 2000ms - * 7 4000ms - * @retval 0 设置成功 - * 1 设置失败 - */ -uint8_t bmp280_setConfig(uint8_t Standbyt,uint8_t filter) -{ - uint8_t temp=0; - temp = Standbyt<<5; - filter&=0x07; - filter=filter<<2; - temp|=filter; - return bmp280_writeReg(BMP280_CONFIG,&temp); -} - - - /** - * @brief 获取校准系数 - * @param calib 储存系数的结构体 - * @retval 无 - */ -void bmp280_getCalibration(bmp280_calib *calib) -{ - uint8_t buf[20]; - bmp280_readReg(BMP280_DIGT,buf,6); - calib->dig_t1 =(uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0])); - calib->dig_t2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2])); - calib->dig_t3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4])); - bmp280_readReg(BMP280_DIGP,buf,18); - calib->dig_p1 = (uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0])); - calib->dig_p2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2])); - calib->dig_p3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4])); - calib->dig_p4 =(int16_t)(bmp280_msblsb_to_u16(buf[7], buf[6])); - calib->dig_p5 =(int16_t)(bmp280_msblsb_to_u16(buf[9], buf[8])); - calib->dig_p6 =(int16_t)(bmp280_msblsb_to_u16(buf[11], buf[10])); - calib->dig_p7 =(int16_t)(bmp280_msblsb_to_u16(buf[13], buf[12])); - calib->dig_p8 =(int16_t)(bmp280_msblsb_to_u16(buf[15], buf[14])); - calib->dig_p9 =(int16_t)(bmp280_msblsb_to_u16(buf[17], buf[16])); -} - - - - /** - * @brief 获取温度 - * @param calib 系数的结构体 - * *temperature 温度值指针 - * *t_fine 精细分辨率温度值指针 - * @retval 无 - */ -void bmp280_getTemperature(bmp280_calib *calib,double *temperature,int32_t *t_fine) -{ - uint8_t buf[3]; - uint32_t data_xlsb; - uint32_t data_lsb; - uint32_t data_msb; - int32_t uncomp_temperature; - double var1, var2; - - bmp280_readReg(BMP280_TEMP,buf,3); - data_msb = (int32_t)buf[0] << 12; - data_lsb = (int32_t)buf[1] << 4; - data_xlsb = (int32_t)buf[2] >> 4; - uncomp_temperature = (int32_t)(data_msb | data_lsb | data_xlsb); - - - var1 = (((double) uncomp_temperature) / 16384.0 - ((double) calib->dig_t1) / 1024.0) * - ((double) calib->dig_t2); - var2 = - ((((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0) * - (((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0)) * - ((double) calib->dig_t3); - *t_fine = (int32_t) (var1 + var2); - *temperature = (var1 + var2) / 5120.0; -} - - - /** - * @brief 获取气压 - * @param calib 系数的结构体 - * *pressure 气压值指针 - * *t_fine 精细分辨率温度值指针 - * @retval 无 - */ -void bmp280_getPressure(bmp280_calib *calib,double *pressure,int32_t *t_fine) -{ - uint8_t buf[3]; - uint32_t data_xlsb; - uint32_t data_lsb; - uint32_t data_msb; - int32_t uncomp_pressure; - double var1, var2; - - bmp280_readReg(BMP280_PRES,buf,3); - data_msb = (uint32_t)buf[0] << 12; - data_lsb = (uint32_t)buf[1] << 4; - data_xlsb = (uint32_t)buf[2] >> 4; - uncomp_pressure = (data_msb | data_lsb | data_xlsb); - - var1 = ((double) *t_fine / 2.0) - 64000.0; - var2 = var1 * var1 * ((double) calib->dig_p6) / 32768.0; - var2 = var2 + var1 * ((double) calib->dig_p5) * 2.0; - var2 = (var2 / 4.0) + (((double) calib->dig_p4) * 65536.0); - var1 = (((double)calib->dig_p3) * var1 * var1 / 524288.0 + ((double)calib->dig_p2) * var1) / - 524288.0; - var1 = (1.0 + var1 / 32768.0) * ((double) calib->dig_p1); - *pressure = 1048576.0 - (double)uncomp_pressure; - *pressure = (*pressure - (var2 / 4096.0)) * 6250.0 / var1; - var1 = ((double)calib->dig_p9) * *pressure * *pressure / 2147483648.0; - var2 = *pressure * ((double)calib->dig_p8) / 32768.0; - - *pressure = *pressure + (var1 + var2 + ((double)calib->dig_p7)) / 16.0; -} - - - /** - * @brief 初始化 - * @param *calib 系数的结构体指针 - * @retval 0 设置成功 - * 1 设置失败 - */ -uint8_t bmp280_init(bmp280_calib *calib) -{ - uint8_t rslt; - rslt = bmp280_get_id(); - if(rslt == BMP2_CHIP_ID) - { - bmp280_getCalibration(calib); - rslt = bmp280_setOversampling(5,2); - if(rslt) - { - return 1; - } - rslt = bmp280_setConfig(0,4); - if(rslt) - { - return 1; - } - rslt = bmp280_setMode(2); - if(rslt) - { - return 1; - } - } - else - { - return 1; - } - return 0; -} - - - /** - * @brief 获取最终数据 - * @param *calib 系数的结构体指针 - * @retval 无 - */ -void bmp280_getdata(bmp280_calib *calib,float *temperature,float *pressure) -{ - double temp_T,temp_P; - int32_t t_fine; - bmp280_getTemperature(calib,&temp_T,&t_fine); - bmp280_getPressure(calib,&temp_P,&t_fine); - *temperature = (float)temp_T; - *pressure = (float)temp_P; -} diff --git a/assets/User_code/device/bmp280_i2c.h b/assets/User_code/device/bmp280_i2c.h deleted file mode 100644 index 9ec329d..0000000 --- a/assets/User_code/device/bmp280_i2c.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -/*底层接口定义*/ -#include "bsp/i2c.h" -#include "stdint.h" - -#define BMP280_I2C_ADDR 0x76 // BMP280 默认 I2C 地址 - -/*寄存器地址*/ -#define BMP280_ID 0xD0 // 设备ID地址 -#define BMP280_RESET 0xE0 // 设备重启 -#define BMP280_STATUS 0xF3 // 设备状态 -#define BMP280_CTRL_MEAS 0xF4 // 数据采集和模式设置 -#define BMP280_CONFIG 0xF5 // 采样速率,滤波器和接口设置 -#define BMP280_DIGT 0x88 // 温度校准系数起始位置 -#define BMP280_DIGP 0x8E // 气压校准系数起始位置 -#define BMP280_TEMP 0xFA // 温度储存起始位置 -#define BMP280_PRES 0xF7 // 气压储存起始位置 - -#define BMP2_CHIP_ID 0x58 // 设备ID地址 - -#define bmp280_msblsb_to_u16(msb, lsb) (((uint16_t)msb << 8) | ((uint16_t)lsb)) - -typedef struct { - unsigned short dig_t1; - signed short dig_t2; - signed short dig_t3; - unsigned short dig_p1; - signed short dig_p2; - signed short dig_p3; - signed short dig_p4; - signed short dig_p5; - signed short dig_p6; - signed short dig_p7; - signed short dig_p8; - signed short dig_p9; -} bmp280_calib; - -uint8_t bmp280_get_id(void); -uint8_t bmp280_reset(void); -uint8_t bmp280_getStatus(void); -uint8_t bmp280_setMode(uint8_t mode); -uint8_t bmp280_setOversampling(uint8_t osrs_p, uint8_t osrs_t); -uint8_t bmp280_setConfig(uint8_t Standbyt, uint8_t filter); -void bmp280_getCalibration(bmp280_calib *calib); -void bmp280_getTemperature(bmp280_calib *calib, double *temperature, int32_t *t_fine); -void bmp280_getPressure(bmp280_calib *calib, double *pressure, int32_t *t_fine); -uint8_t bmp280_init(bmp280_calib *calib); -void bmp280_getdata(bmp280_calib *calib, float *temperature, float *pressure); diff --git a/assets/User_code/device/key_gpio.c b/assets/User_code/device/key_gpio.c deleted file mode 100644 index a5ce605..0000000 --- a/assets/User_code/device/key_gpio.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "key_gpio.h" -#include "device.h" -#include "bsp/gpio_exti.h" -#include "gpio.h" -/* Private define ----------------------------------------------------------- */ -#define DEBOUNCE_TIME_MS 20 -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -/* ⲿ־λ־λ */ -volatile uint8_t key_flag = 0; // 1=£0=ɿ -volatile uint8_t key_exti = 0; -volatile uint8_t key_pressed = 0; // ȫֱ־λ -static uint32_t last_debounce_time = 0; // - -/* Private function -------------------------------------------------------- */ -static void KEY_Interrupt_Callback(void) { - // л־λ״̬ - - key_flag = !key_flag; - key_exti = 1; - -} - -/* Exported functions ------------------------------------------------------- */ -void KEY_Process(void) -{ - BSP_GPIO_RegisterCallback(BSP_GPIO_USER_KEY, BSP_GPIO_EXTI_CB, KEY_Interrupt_Callback); - - if(key_exti == 1) - { - uint32_t now = HAL_GetTick(); - // Ƿ񳬹ʱ - if ((now - last_debounce_time) > DEBOUNCE_TIME_MS) { - // Ч״̬谴Ϊ͵ƽ - if(key_flag == 0) - { - key_pressed = DEVICE_KEY_RELEASED; - } - if(key_flag == 1) - { - key_pressed = DEVICE_KEY_PRESSED; - } - } - else - { - HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6); - - } - last_debounce_time = now; // ʱ - key_exti = 0; - } - else - { - - } - } - -uint8_t KEY_Get_State(void) { - return key_pressed; -} - - diff --git a/assets/User_code/device/key_gpio.h b/assets/User_code/device/key_gpio.h deleted file mode 100644 index 8e0024a..0000000 --- a/assets/User_code/device/key_gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef KEY_GPIO_H -#define KEY_GPIO_H -/* Includes ----------------------------------------------------------------- */ -#include -#include "main.h" - -/* Exported constants ------------------------------------------------------- */ -/* Exported macro ----------------------------------------------------------- */ -/* Exported types ----------------------------------------------------------- */ - -///* KEY״̬ */ -typedef enum -{ - DEVICE_KEY_RELEASED, //ͷ - DEVICE_KEY_PRESSED, // -} DEVICE_KEY_Status_t; - -void KEY_Process(void); -uint8_t KEY_Get_State(void); - -#endif diff --git a/assets/User_code/device/oled.c b/assets/User_code/device/oled.c new file mode 100644 index 0000000..3e9688f --- /dev/null +++ b/assets/User_code/device/oled.c @@ -0,0 +1,381 @@ +/* + OLED显示模块。 + + 使用SPI通信时,需要#define OLED_USE_SPI + 使用I2C通信时,需要#define OLED_USE_I2C + +*/ + +/* Includes ----------------------------------------------------------------- */ +/* Include 自身的头文件。*/ +#include "oled.h" + +/* Include 标准库。*/ +#include +#include +#include + +/* Include HAL相关的头文件。*/ +#include "bsp_delay.h" +#include "bsp_spi.h" +#include + +#ifdef OLED_USE_SPI +#include "spi.h" +# + +#elif defined OLED_USE_I2C +#include "i2c.h" + +#endif + + +/* Include Component相关的头文件 */ +/* Private define ----------------------------------------------------------- */ +/* Private macro ------------------------------------------------------------ */ +#ifdef OLED_USE_SPI + +#define OLED_CMD_Set() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET) +#define OLED_CMD_Clr() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET) + +#define OLED_RST_Set() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET) +#define OLED_RST_Clr() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET) + +#elif defined OLED_USE_I2C +#define OLED_I2C_HANDLE hi2c1 + +#endif + +/* Private typedef ---------------------------------------------------------- */ +typedef enum { + OLED_WriteCMD = 0, + OLED_WriteData = 1, +}OLED_Write_t; + + +/* Private variables -------------------------------------------------------- */ +static const uint8_t oled_font[95][8] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, /* " ", 0 */ + {0x00,0x00,0x00,0xcf,0xcf,0x00,0x00,0x00,}, /* "!", 1 */ + {0x00,0x0c,0x06,0x00,0x0c,0x06,0x00,0x00,}, /* """, 2 */ + {0x24,0xe4,0x3c,0x27,0xe4,0x3c,0x27,0x24,}, /* "#", 3 */ + {0x00,0x20,0x46,0xf9,0x9f,0x62,0x04,0x00,}, /* "$", 4 */ + {0x06,0x09,0xc6,0x30,0x0c,0x63,0x90,0x60,}, /* "%", 5 */ + {0x00,0x00,0x6e,0x91,0xa9,0x46,0xa0,0x00,}, /* "&", 6 */ + {0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,}, /* "'", 7 */ + {0x00,0x00,0x3c,0x42,0x81,0x00,0x00,0x00,}, /* "(", 8 */ + {0x00,0x00,0x00,0x81,0x42,0x3c,0x00,0x00,}, /* ")", 9 */ + {0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00,}, /* "*", 10 */ + {0x00,0x10,0x10,0xfc,0x10,0x10,0x00,0x00,}, /* "+", 11 */ + {0x00,0x00,0x00,0xc0,0x60,0x00,0x00,0x00,}, /* ",", 12 */ + {0x00,0x00,0x10,0x10,0x10,0x10,0x00,0x00,}, /* "-", 13 */ + {0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00,}, /* ".", 14 */ + {0x00,0x00,0x00,0xc0,0x38,0x07,0x00,0x00,}, /* "/", 15 */ + {0x00,0x00,0x7c,0x92,0x8a,0x7c,0x00,0x00,}, /* "0", 16 */ + {0x00,0x00,0x00,0x84,0xfe,0x80,0x00,0x00,}, /* "1", 17 */ + {0x00,0x00,0x8c,0xc2,0xa2,0x9c,0x00,0x00,}, /* "2", 18 */ + {0x00,0x00,0x44,0x92,0x92,0x6c,0x00,0x00,}, /* "3", 19 */ + {0x00,0x20,0x38,0x24,0xfe,0x20,0x00,0x00,}, /* "4", 20 */ + {0x00,0x00,0x5e,0x92,0x92,0x62,0x00,0x00,}, /* "5", 21 */ + {0x00,0x00,0x78,0x94,0x92,0x62,0x00,0x00,}, /* "6", 22 */ + {0x00,0x00,0x82,0x62,0x1a,0x06,0x00,0x00,}, /* "7", 23 */ + {0x00,0x00,0x6c,0x92,0x92,0x6c,0x00,0x00,}, /* "8", 24 */ + {0x00,0x00,0x8c,0x52,0x32,0x1c,0x00,0x00,}, /* "9", 25 */ + {0x00,0x00,0x00,0x6c,0x6c,0x00,0x00,0x00,}, /* ":", 26 */ + {0x00,0x00,0x80,0xec,0x6c,0x00,0x00,0x00,}, /* ";", 27 */ + {0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,}, /* "<", 28 */ + {0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,}, /* "=", 29 */ + {0x00,0x00,0x00,0x44,0x28,0x10,0x00,0x00,}, /* ">", 30 */ + {0x00,0x00,0x0c,0xa2,0x92,0x1c,0x00,0x00,}, /* "?", 31 */ + {0x00,0x3c,0x42,0x99,0xa5,0xa2,0x3c,0x00,}, /* "@", 32 */ + {0x00,0xe0,0x1c,0x12,0x12,0x1c,0xe0,0x00,}, /* "A", 33 */ + {0x00,0xfe,0x92,0x92,0x9c,0x90,0x60,0x00,}, /* "B", 34 */ + {0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x00,}, /* "C", 35 */ + {0x00,0xfe,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "D", 36 */ + {0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0x00,}, /* "E", 37 */ + {0x00,0xfe,0x12,0x12,0x12,0x12,0x02,0x00,}, /* "F", 38 */ + {0x00,0x7c,0x82,0x92,0x92,0x72,0x00,0x00,}, /* "G", 39 */ + {0x00,0xfe,0x10,0x10,0x10,0x10,0xfe,0x00,}, /* "H", 40 */ + {0x00,0x82,0x82,0xfe,0x82,0x82,0x00,0x00,}, /* "I", 41 */ + {0x00,0x82,0x82,0x7e,0x02,0x02,0x00,0x00,}, /* "J", 42 */ + {0x00,0xfe,0x10,0x28,0x44,0x82,0x00,0x00,}, /* "K", 43 */ + {0x00,0xfe,0x80,0x80,0x80,0x80,0x00,0x00,}, /* "L", 44 */ + {0xfc,0x02,0x04,0xf8,0x04,0x02,0xfc,0x00,}, /* "M", 45 */ + {0x00,0xfe,0x04,0x18,0x30,0x40,0xfe,0x00,}, /* "N", 46 */ + {0x00,0x7c,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "O", 47 */ + {0x00,0x00,0xfe,0x12,0x12,0x0c,0x00,0x00,}, /* "P", 48 */ + {0x00,0x00,0x3c,0x42,0xc2,0xbc,0x00,0x00,}, /* "Q", 49 */ + {0x00,0x00,0xfe,0x32,0x52,0x8c,0x00,0x00,}, /* "R", 50 */ + {0x00,0x00,0x4c,0x92,0x92,0x64,0x00,0x00,}, /* "S", 51 */ + {0x00,0x02,0x02,0xfe,0x02,0x02,0x00,0x00,}, /* "T", 52 */ + {0x00,0x7e,0x80,0x80,0x80,0x80,0x7e,0x00,}, /* "U", 53 */ + {0x00,0x0c,0x30,0xc0,0x30,0x0c,0x00,0x00,}, /* "V", 54 */ + {0x7c,0x80,0x80,0x78,0x80,0x80,0x7c,0x00,}, /* "W", 55 */ + {0x00,0x84,0x48,0x30,0x30,0x48,0x84,0x00,}, /* "X", 56 */ + {0x00,0x06,0x08,0xf0,0x08,0x06,0x00,0x00,}, /* "Y", 57 */ + {0x00,0x00,0xc2,0xa2,0x92,0x8e,0x00,0x00,}, /* "Z", 58 */ + {0x00,0x00,0xfe,0x82,0x82,0x82,0x00,0x00,}, /* "[", 59 */ + {0x00,0x00,0x06,0x18,0x60,0x80,0x00,0x00,}, /* "\", 60 */ + {0x00,0x00,0x82,0x82,0x82,0xfe,0x00,0x00,}, /* "]", 61 */ + {0x00,0x30,0x0c,0x02,0x0c,0x30,0x00,0x00,}, /* "^", 62 */ + {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,}, /* "_", 63 */ + {0x00,0x00,0x04,0x0c,0x18,0x00,0x00,0x00,}, /* "`", 64 */ + {0x00,0x00,0x60,0x90,0x90,0xe0,0x00,0x00,}, /* "a", 65 */ + {0x00,0x00,0xf8,0xa0,0xe0,0x00,0x00,0x00,}, /* "b", 66 */ + {0x00,0x00,0x60,0x90,0x90,0x00,0x00,0x00,}, /* "c", 67 */ + {0x00,0x00,0xe0,0xa0,0xf8,0x00,0x00,0x00,}, /* "d", 68 */ + {0x00,0x00,0x70,0xa8,0xa8,0x90,0x00,0x00,}, /* "e", 69 */ + {0x00,0x00,0x10,0xf8,0x14,0x00,0x00,0x00,}, /* "f", 70 */ + {0x00,0x00,0xd8,0xa4,0x7c,0x00,0x00,0x00,}, /* "g", 71 */ + {0x00,0x00,0xf8,0x20,0xe0,0x00,0x00,0x00,}, /* "h", 72 */ + {0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x00,}, /* "i", 73 */ + {0x00,0x00,0x40,0x90,0x74,0x00,0x00,0x00,}, /* "j", 74 */ + {0x00,0x00,0xf8,0x60,0x90,0x00,0x00,0x00,}, /* "k", 75 */ + {0x00,0x00,0x78,0x80,0x80,0x00,0x00,0x00,}, /* "l", 76 */ + {0x00,0xe0,0x10,0xe0,0x10,0xe0,0x00,0x00,}, /* "m", 77 */ + {0x00,0x00,0xf0,0x10,0x10,0xe0,0x00,0x00,}, /* "n", 78 */ + {0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,}, /* "o", 79 */ + {0x00,0x00,0xf0,0x48,0x48,0x30,0x00,0x00,}, /* "p", 80 */ + {0x00,0x00,0x30,0x48,0x48,0xf0,0x00,0x00,}, /* "q", 81 */ + {0x00,0x00,0x00,0xf0,0x20,0x10,0x00,0x00,}, /* "r", 82 */ + {0x00,0x00,0x90,0xa8,0xa8,0x48,0x00,0x00,}, /* "s", 83 */ + {0x00,0x10,0x10,0xf8,0x90,0x90,0x00,0x00,}, /* "t", 84 */ + {0x00,0x00,0x78,0x80,0x80,0xf8,0x00,0x00,}, /* "u", 85 */ + {0x00,0x18,0x60,0x80,0x60,0x18,0x00,0x00,}, /* "v", 86 */ + {0x00,0x38,0xc0,0x38,0xc0,0x38,0x00,0x00,}, /* "w", 87 */ + {0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,}, /* "x", 88 */ + {0x00,0x8c,0x50,0x20,0x10,0x0c,0x00,0x00,}, /* "y", 89 */ + {0x00,0x88,0xc8,0xa8,0x98,0x88,0x00,0x00,}, /* "z", 90 */ + {0x00,0x00,0x10,0x7c,0x82,0x00,0x00,0x00,}, /* "{", 91 */ + {0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,}, /* "|", 92 */ + {0x00,0x00,0x00,0x82,0x7c,0x10,0x00,0x00,}, /* "}", 93 */ + {0x00,0x08,0x04,0x04,0x08,0x10,0x10,0x08,}, /* "~", 94 */ +}; + +static const uint8_t gram_logo[8][128] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0E,0X1E,0X3E,0X7E,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFC,0XFC,0XF8,0XF8,0XF0,0XE0,0XC0,0X80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0X1F,0X3F,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XE7,0XC7,0X87,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0F,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0XC0,0XFC,0XFC,0XFC,0XFC,0XFC,0XFD,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFC,0XFC,0XFC,0XFC,0XFC,0XFC,0XFC,0XFC,0XFC,0XFC,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X7F,0X3F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0X80,0XF0,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0X1F,0X3F,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEF,0XCF,0X87,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0XE0,0XFC,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0X40,0X40,0X40,0XC0,0XC0,0XC0,0XC0,0XC1,0XC3,0XC7,0XCF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFC,0XF8,0XF0,0XE0,0XC0,0X80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0C,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x07,0x07,0x0F,0x0F,0X1F,0X1F,0X3F,0X3F,0X7F,0X7F,0XFF,0XF3,0XE3,0XC3,0X83,0x03,0x03,0x03,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x78,0x7B,0x1B,0x1B,0x1B,0x7B,0x7F,0x6F,0x4E,0x00,0x3E,0x7F,0x63,0x63,0x63,0x7F,0x3E,0x00,0x78,0x7B,0x6B,0x6B,0x6B,0x6B,0x7B,0x7F,0x36,0x00,0x3E,0x7F,0x63,0x63,0x63,0x7F,0x3E,0x40,0x60,0x78,0x3D,0x07,0x1F,0x7C,0x70,0x1D,0x07,0x7F,0x78,0x40,0x00,0x60,0x70,0x38,0x5D,0x6F,0x67,0x6F,0x7C,0x70,0x40,0x00,0x40,0x66,0x6F,0x6B,0x6B,0x6B,0x6B,0x7B,0x31,0x02,0x03,0x03,0x7F,0x7F,0x03,0x03,0x61,0x68,0x6B,0x6B,0x6B,0x6B,0x6B,0x0B,0x03,0x60,0x78,0x7B,0x1B,0x1B,0x1B,0x7B,0x7B,0x6F,0x4E,0x00,0x46,0x6F,0x6F,0x6B,0x6B,0x6B,0x7B,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +static OLED_t *goled; +static bool inited = false; + +/* Private function ---------------------------------------------- */ +static void OLED_WriteByte(uint8_t data, OLED_Write_t type) { + +#ifdef OLED_USE_SPI + switch(type) { + case OLED_WriteCMD: + OLED_CMD_Clr(); + break; + + case OLED_WriteData: + OLED_CMD_Set(); + break; + } + BSP_SPI_Transmit(BSP_SPI_OLED, &data, 1); + +#elif defined OLED_USE_I2C + uint8_t cmd_data[2]; + + switch(type) { + case OLED_WriteCMD: + cmd_data[0] = 0x00; + break; + + case OLED_WriteData: + cmd_data[0] = 0x40; + break; + } + cmd_data[1] = data; + HAL_I2C_Master_Transmit_DMA(OLED_I2C, OLED_I2C_ADDRESS, cmd_data, 2); +#endif + + BSP_Delay(1); +} + +static void OLED_WriteSequenceData(uint8_t *data, uint16_t len) { +#ifdef OLED_USE_SPI + OLED_CMD_Set(); + HAL_SPI_Transmit_DMA(&hspi1, data, len); + +#elif defined OLED_USE_I2C + /* TODO */ + uint8_t cmd_data[2]; + cmd_data[0] = 0x40; + cmd_data[1] = data; + HAL_I2C_Master_Transmit_DMA(OLED_I2C, OLED_I2C_ADDRESS, cmd_data, 2); +#endif +} + +/* Exported functions ------------------------------------------------------- */ +int8_t OLED_Init(OLED_t *oled) { + if (oled == NULL) + return -1; + + if (inited) + return -1; + + oled->cursor.column = 0; + oled->cursor.page = 0; + oled->modified = true; + + goled = oled; + + OLED_RST_Clr(); + BSP_Delay(1); + OLED_RST_Set(); + BSP_Delay(5); + + OLED_WriteByte(0xae, OLED_WriteCMD); /* Dot martix display off. */ + OLED_WriteByte(0x00, OLED_WriteCMD); /* Set lower column address:(00H~0FH). */ + OLED_WriteByte(0x10, OLED_WriteCMD); /* Set higher column address:(10H~1FH). */ + OLED_WriteByte(0x20, OLED_WriteCMD); /* Set Memory Addressing Mode */ + OLED_WriteByte(0x10, OLED_WriteCMD); /* 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid */ + OLED_WriteByte(0x32, OLED_WriteCMD); /* Set pump voltage 8v. */ + OLED_WriteByte(0x40, OLED_WriteCMD); /* Set display start line:(40H~7FH). */ + OLED_WriteByte(0x81, OLED_WriteCMD); /* Contarst control. */ + OLED_WriteByte(0x6f, OLED_WriteCMD); /* Contarst: 0x00~0xff. */ + OLED_WriteByte(0xa1, OLED_WriteCMD); /* Set segment re-map. 0xa0 or 0xa1. */ + OLED_WriteByte(0xa4, OLED_WriteCMD); /* Entire display off. */ + OLED_WriteByte(0xa6, OLED_WriteCMD); /* Set normal display. */ + OLED_WriteByte(0xa8, OLED_WriteCMD); /* Set multiplex ratio. */ + OLED_WriteByte(0x3f, OLED_WriteCMD); + OLED_WriteByte(0xad, OLED_WriteCMD); /* Set DC/DC booster. */ + OLED_WriteByte(0x8b, OLED_WriteCMD); + OLED_WriteByte(0xb0, OLED_WriteCMD); /* Set page address. */ + OLED_WriteByte(0xc8, OLED_WriteCMD); /* Com scan COM0->COM63. */ + OLED_WriteByte(0xd3, OLED_WriteCMD); /* Set display offset. */ + OLED_WriteByte(0x00, OLED_WriteCMD); + OLED_WriteByte(0xd5, OLED_WriteCMD); /* Set frame frequency. */ + OLED_WriteByte(0xf0, OLED_WriteCMD); + OLED_WriteByte(0xd9, OLED_WriteCMD); /* Set pre_charge period. */ + OLED_WriteByte(0x22, OLED_WriteCMD); + OLED_WriteByte(0xda, OLED_WriteCMD); /* Com pin configuration. */ + OLED_WriteByte(0x12, OLED_WriteCMD); + OLED_WriteByte(0xdb, OLED_WriteCMD); /* Set vcom deselect level. */ + OLED_WriteByte(0x20, OLED_WriteCMD); + OLED_WriteByte(0x8d, OLED_WriteCMD); /* Set DC-DC enable */ + OLED_WriteByte(0x14, OLED_WriteCMD); + OLED_WriteByte(0xaf, OLED_WriteCMD); /* Display on. */ + + memcmp(oled->gram, gram_logo, sizeof(oled->gram)); + + OLED_SetAllRam(oled, OLED_PEN_WRITE); /* Clear memory. */ + + OLED_Refresh(oled); /* Display initial picture. */ + return 0; +} + +OLED_t *OLED_GetDevice(void) { + if (inited) { + return goled; + } + return NULL; +} + +int8_t OLED_PrintRam(OLED_t *oled, const char* str) { + if (str == NULL) + return -1; + + oled->modified = true; + + for (uint16_t i = 0; str[i] != '\0'; i++) { + uint8_t c = str[i]; + if (c < 32) { + switch (c) { + case '\n': + oled->cursor.page ++; + oled->cursor.column = 0; + break; + + case '\t': + oled->cursor.column += 16; + break; + } + } else if (c < 126) { + if (oled->cursor.column == 128) { + oled->cursor.page ++; + oled->cursor.column = 0; + } + if (oled->cursor.page == 8) { + OLED_SetAllRam(oled, OLED_PEN_CLEAR); + oled->cursor.page = 0; + } + memcpy(&oled->gram[oled->cursor.page][oled->cursor.column], oled_font[c- 32], sizeof(oled_font[0])); + oled->cursor.column += 8; + } + } + return 0; +} + +uint8_t OLED_RewindRam(OLED_t *oled) { + oled->modified = true; + + OLED_SetAllRam(oled, OLED_PEN_CLEAR); + + oled->cursor.page = 0; + oled->cursor.column = 0; + return 0; +} + +uint8_t OLED_SetAllRam(OLED_t *oled, OLED_Pen_t pen) { + switch(pen) { + case OLED_PEN_WRITE: + memset(oled->gram, -1, sizeof(oled->gram)); + break; + + case OLED_PEN_CLEAR: + memset(oled->gram, 0, sizeof(oled->gram)); + break; + + case OLED_PEN_INVERSION: + for (uint8_t i = 0; i < 8; i++) { + for (uint8_t n = 0; n < 128; n++) { + oled->gram[i][n] = ~oled->gram[i][n]; + } + } + break; + } + return 0; +} + +uint8_t OLED_DisplayOn(OLED_t *oled) { + OLED_WriteByte(0x8d, OLED_WriteCMD); + OLED_WriteByte(0x14, OLED_WriteCMD); + OLED_WriteByte(0xaf, OLED_WriteCMD); + return 0; +} + +uint8_t OLED_DisplayOff(OLED_t *oled) { + OLED_WriteByte(0x8d, OLED_WriteCMD); + OLED_WriteByte(0x10, OLED_WriteCMD); + OLED_WriteByte(0xae, OLED_WriteCMD); + return 0; +} + + +void OLED_SetCursor(uint8_t x, uint8_t y) +{ + OLED_WriteByte((0xb0 + y), OLED_WriteCMD); /*set page address y */ + OLED_WriteByte(((x&0xf0)>>4)|0x10, OLED_WriteCMD); /*set column high address */ + OLED_WriteByte((x&0x0f), OLED_WriteCMD); /*set column low address */ +} + +uint8_t OLED_Refresh(OLED_t *oled) { + for (uint8_t i = 0; i < 8; i++) { + OLED_SetCursor(0, i); + for (uint8_t n = 0; n < 8; n++) { + OLED_WriteByte(oled->gram[i][n], OLED_WriteData); + } + } + oled->modified = false; + + return 0; +} diff --git a/assets/User_code/device/oled.h b/assets/User_code/device/oled.h new file mode 100644 index 0000000..e296bc6 --- /dev/null +++ b/assets/User_code/device/oled.h @@ -0,0 +1,45 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include +#include + +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +typedef enum { + OLED_PEN_CLEAR = 0, + OLED_PEN_WRITE = 1, + OLED_PEN_INVERSION = 2, +} OLED_Pen_t; + +typedef struct { + uint8_t column; + s uint8_t page; +} OLED_Cursor_t; + +typedef struct { + OLED_Cursor_t cursor; + uint8_t gram[8][128]; + bool modified; +} OLED_t; + +/* Exported functions prototypes -------------------------------------------- */ +uint8_t OLED_Init(OLED_t *oled); +OLED_t *OLED_GetDevice(void); + +uint8_t OLED_PrintRam(OLED_t *oled, const char *str); +uint8_t OLED_RewindRam(OLED_t *oled); +uint8_t OLED_SetAllRam(OLED_t *oled, OLED_Pen_t pen); + +uint8_t OLED_DisplayOn(OLED_t *oled); +uint8_t OLED_DisplayOff(OLED_t *oled); +uint8_t OLED_Refresh(OLED_t *oled); + +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/device/oled_i2c.c b/assets/User_code/device/oled_i2c.c deleted file mode 100644 index f0100a0..0000000 --- a/assets/User_code/device/oled_i2c.c +++ /dev/null @@ -1,267 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "device/oled_i2c.h" -#include "bsp/i2c.h" -#include -#include -/* Private define ----------------------------------------------------------- */ -#define OLED_I2C_ADDR 0x78 // OLED I2C 地址 -#define OLED_WIDTH 128 -#define OLED_HEIGHT 64 - -/* Private variables -------------------------------------------------------- */ -static uint8_t oled_buffer[OLED_WIDTH * OLED_HEIGHT / 8]; -static struct { - uint8_t x_min; - uint8_t x_max; - uint8_t y_min; - uint8_t y_max; - uint8_t dirty; // 标志是否有脏区域 -} dirty_rect = {0, 0, 0, 0, 0}; - -/* Private function prototypes ---------------------------------------------- */ -static void OLED_WriteCommand(uint8_t cmd) { - uint8_t data[2] = {0x00, cmd}; - HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, data, 2, HAL_MAX_DELAY); -} - -static void OLED_WriteData(uint8_t *data, uint16_t size) { - uint8_t buffer[size + 1]; - buffer[0] = 0x40; - memcpy(&buffer[1], data, size); - HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, buffer, size + 1, HAL_MAX_DELAY); -} - -static void OLED_MarkDirty(uint8_t x, uint8_t y); -static void OLED_UpdateDirtyScreen(void); - -static const uint8_t oled_font[95][8] = { - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, /* " ", 0 */ - {0x00,0x00,0x00,0xcf,0xcf,0x00,0x00,0x00,}, /* "!", 1 */ - {0x00,0x0c,0x06,0x00,0x0c,0x06,0x00,0x00,}, /* """, 2 */ - {0x24,0xe4,0x3c,0x27,0xe4,0x3c,0x27,0x24,}, /* "#", 3 */ - {0x00,0x20,0x46,0xf9,0x9f,0x62,0x04,0x00,}, /* "$", 4 */ - {0x06,0x09,0xc6,0x30,0x0c,0x63,0x90,0x60,}, /* "%", 5 */ - {0x00,0x00,0x6e,0x91,0xa9,0x46,0xa0,0x00,}, /* "&", 6 */ - {0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,}, /* "'", 7 */ - {0x00,0x00,0x3c,0x42,0x81,0x00,0x00,0x00,}, /* "(", 8 */ - {0x00,0x00,0x00,0x81,0x42,0x3c,0x00,0x00,}, /* ")", 9 */ - {0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00,}, /* "*", 10 */ - {0x00,0x10,0x10,0xfc,0x10,0x10,0x00,0x00,}, /* "+", 11 */ - {0x00,0x00,0x00,0xc0,0x60,0x00,0x00,0x00,}, /* ",", 12 */ - {0x00,0x00,0x10,0x10,0x10,0x10,0x00,0x00,}, /* "-", 13 */ - {0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00,}, /* ".", 14 */ - {0x00,0x00,0x00,0xc0,0x38,0x07,0x00,0x00,}, /* "/", 15 */ - {0x00,0x00,0x7c,0x92,0x8a,0x7c,0x00,0x00,}, /* "0", 16 */ - {0x00,0x00,0x00,0x84,0xfe,0x80,0x00,0x00,}, /* "1", 17 */ - {0x00,0x00,0x8c,0xc2,0xa2,0x9c,0x00,0x00,}, /* "2", 18 */ - {0x00,0x00,0x44,0x92,0x92,0x6c,0x00,0x00,}, /* "3", 19 */ - {0x00,0x20,0x38,0x24,0xfe,0x20,0x00,0x00,}, /* "4", 20 */ - {0x00,0x00,0x5e,0x92,0x92,0x62,0x00,0x00,}, /* "5", 21 */ - {0x00,0x00,0x78,0x94,0x92,0x62,0x00,0x00,}, /* "6", 22 */ - {0x00,0x00,0x82,0x62,0x1a,0x06,0x00,0x00,}, /* "7", 23 */ - {0x00,0x00,0x6c,0x92,0x92,0x6c,0x00,0x00,}, /* "8", 24 */ - {0x00,0x00,0x8c,0x52,0x32,0x1c,0x00,0x00,}, /* "9", 25 */ - {0x00,0x00,0x00,0x6c,0x6c,0x00,0x00,0x00,}, /* ":", 26 */ - {0x00,0x00,0x80,0xec,0x6c,0x00,0x00,0x00,}, /* ";", 27 */ - {0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,}, /* "<", 28 */ - {0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,}, /* "=", 29 */ - {0x00,0x00,0x00,0x44,0x28,0x10,0x00,0x00,}, /* ">", 30 */ - {0x00,0x00,0x0c,0xa2,0x92,0x1c,0x00,0x00,}, /* "?", 31 */ - {0x00,0x3c,0x42,0x99,0xa5,0xa2,0x3c,0x00,}, /* "@", 32 */ - {0x00,0xe0,0x1c,0x12,0x12,0x1c,0xe0,0x00,}, /* "A", 33 */ - {0x00,0xfe,0x92,0x92,0x9c,0x90,0x60,0x00,}, /* "B", 34 */ - {0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x00,}, /* "C", 35 */ - {0x00,0xfe,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "D", 36 */ - {0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0x00,}, /* "E", 37 */ - {0x00,0xfe,0x12,0x12,0x12,0x12,0x02,0x00,}, /* "F", 38 */ - {0x00,0x7c,0x82,0x92,0x92,0x72,0x00,0x00,}, /* "G", 39 */ - {0x00,0xfe,0x10,0x10,0x10,0x10,0xfe,0x00,}, /* "H", 40 */ - {0x00,0x82,0x82,0xfe,0x82,0x82,0x00,0x00,}, /* "I", 41 */ - {0x00,0x82,0x82,0x7e,0x02,0x02,0x00,0x00,}, /* "J", 42 */ - {0x00,0xfe,0x10,0x28,0x44,0x82,0x00,0x00,}, /* "K", 43 */ - {0x00,0xfe,0x80,0x80,0x80,0x80,0x00,0x00,}, /* "L", 44 */ - {0xfc,0x02,0x04,0xf8,0x04,0x02,0xfc,0x00,}, /* "M", 45 */ - {0x00,0xfe,0x04,0x18,0x30,0x40,0xfe,0x00,}, /* "N", 46 */ - {0x00,0x7c,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "O", 47 */ - {0x00,0x00,0xfe,0x12,0x12,0x0c,0x00,0x00,}, /* "P", 48 */ - {0x00,0x00,0x3c,0x42,0xc2,0xbc,0x00,0x00,}, /* "Q", 49 */ - {0x00,0x00,0xfe,0x32,0x52,0x8c,0x00,0x00,}, /* "R", 50 */ - {0x00,0x00,0x4c,0x92,0x92,0x64,0x00,0x00,}, /* "S", 51 */ - {0x00,0x02,0x02,0xfe,0x02,0x02,0x00,0x00,}, /* "T", 52 */ - {0x00,0x7e,0x80,0x80,0x80,0x80,0x7e,0x00,}, /* "U", 53 */ - {0x00,0x0c,0x30,0xc0,0x30,0x0c,0x00,0x00,}, /* "V", 54 */ - {0x7c,0x80,0x80,0x78,0x80,0x80,0x7c,0x00,}, /* "W", 55 */ - {0x00,0x84,0x48,0x30,0x30,0x48,0x84,0x00,}, /* "X", 56 */ - {0x00,0x06,0x08,0xf0,0x08,0x06,0x00,0x00,}, /* "Y", 57 */ - {0x00,0x00,0xc2,0xa2,0x92,0x8e,0x00,0x00,}, /* "Z", 58 */ - {0x00,0x00,0xfe,0x82,0x82,0x82,0x00,0x00,}, /* "[", 59 */ - {0x00,0x00,0x06,0x18,0x60,0x80,0x00,0x00,}, /* "\", 60 */ - {0x00,0x00,0x82,0x82,0x82,0xfe,0x00,0x00,}, /* "]", 61 */ - {0x00,0x30,0x0c,0x02,0x0c,0x30,0x00,0x00,}, /* "^", 62 */ - {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,}, /* "_", 63 */ - {0x00,0x00,0x04,0x0c,0x18,0x00,0x00,0x00,}, /* "`", 64 */ - {0x00,0x00,0x60,0x90,0x90,0xe0,0x00,0x00,}, /* "a", 65 */ - {0x00,0x00,0xf8,0xa0,0xe0,0x00,0x00,0x00,}, /* "b", 66 */ - {0x00,0x00,0x60,0x90,0x90,0x00,0x00,0x00,}, /* "c", 67 */ - {0x00,0x00,0xe0,0xa0,0xf8,0x00,0x00,0x00,}, /* "d", 68 */ - {0x00,0x00,0x70,0xa8,0xa8,0x90,0x00,0x00,}, /* "e", 69 */ - {0x00,0x00,0x10,0xf8,0x14,0x00,0x00,0x00,}, /* "f", 70 */ - {0x00,0x00,0xd8,0xa4,0x7c,0x00,0x00,0x00,}, /* "g", 71 */ - {0x00,0x00,0xf8,0x20,0xe0,0x00,0x00,0x00,}, /* "h", 72 */ - {0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x00,}, /* "i", 73 */ - {0x00,0x00,0x40,0x90,0x74,0x00,0x00,0x00,}, /* "j", 74 */ - {0x00,0x00,0xf8,0x60,0x90,0x00,0x00,0x00,}, /* "k", 75 */ - {0x00,0x00,0x78,0x80,0x80,0x00,0x00,0x00,}, /* "l", 76 */ - {0x00,0xe0,0x10,0xe0,0x10,0xe0,0x00,0x00,}, /* "m", 77 */ - {0x00,0x00,0xf0,0x10,0x10,0xe0,0x00,0x00,}, /* "n", 78 */ - {0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,}, /* "o", 79 */ - {0x00,0x00,0xf0,0x48,0x48,0x30,0x00,0x00,}, /* "p", 80 */ - {0x00,0x00,0x30,0x48,0x48,0xf0,0x00,0x00,}, /* "q", 81 */ - {0x00,0x00,0x00,0xf0,0x20,0x10,0x00,0x00,}, /* "r", 82 */ - {0x00,0x00,0x90,0xa8,0xa8,0x48,0x00,0x00,}, /* "s", 83 */ - {0x00,0x10,0x10,0xf8,0x90,0x90,0x00,0x00,}, /* "t", 84 */ - {0x00,0x00,0x78,0x80,0x80,0xf8,0x00,0x00,}, /* "u", 85 */ - {0x00,0x18,0x60,0x80,0x60,0x18,0x00,0x00,}, /* "v", 86 */ - {0x00,0x38,0xc0,0x38,0xc0,0x38,0x00,0x00,}, /* "w", 87 */ - {0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,}, /* "x", 88 */ - {0x00,0x8c,0x50,0x20,0x10,0x0c,0x00,0x00,}, /* "y", 89 */ - {0x00,0x88,0xc8,0xa8,0x98,0x88,0x00,0x00,}, /* "z", 90 */ - {0x00,0x00,0x10,0x7c,0x82,0x00,0x00,0x00,}, /* "{", 91 */ - {0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,}, /* "|", 92 */ - {0x00,0x00,0x00,0x82,0x7c,0x10,0x00,0x00,}, /* "}", 93 */ - {0x00,0x08,0x04,0x04,0x08,0x10,0x10,0x08,}, /* "~", 94 */ -}; - - -/* Exported functions ------------------------------------------------------- */ - -void OLED_Init(void) { - OLED_WriteCommand(0xAE); // 关闭显示 - OLED_WriteCommand(0x20); // 设置内存寻址模式 - OLED_WriteCommand(0x10); // 页寻址模式 - OLED_WriteCommand(0xB0); // 设置页起始地址 - OLED_WriteCommand(0xC8); // 设置COM扫描方向 - OLED_WriteCommand(0x00); // 设置低列地址 - OLED_WriteCommand(0x10); // 设置高列地址 - OLED_WriteCommand(0x40); // 设置显示起始行 - OLED_WriteCommand(0x81); // 设置对比度 - OLED_WriteCommand(0xFF); // 最大对比度 - OLED_WriteCommand(0xA1); // 设置段重映射 - OLED_WriteCommand(0xA6); // 正常显示 - OLED_WriteCommand(0xA8); // 设置多路复用比率 - OLED_WriteCommand(0x3F); // 1/64 - OLED_WriteCommand(0xA4); // 输出跟随 RAM 内容 - OLED_WriteCommand(0xD3); // 设置显示偏移 - OLED_WriteCommand(0x00); // 无偏移 - OLED_WriteCommand(0xD5); // 设置显示时钟分频比/振荡频率 - OLED_WriteCommand(0xF0); // 高频 - OLED_WriteCommand(0xD9); // 设置预充电周期 - OLED_WriteCommand(0x22); // 修复缺少分号 - OLED_WriteCommand(0xDA); // 设置COM引脚硬件配置 - OLED_WriteCommand(0x12); // 修复缺少分号 - OLED_WriteCommand(0xDB); // 设置VCOMH电压 - OLED_WriteCommand(0x20); // 修复缺少分号 - OLED_WriteCommand(0x8D); // 设置充电泵 - OLED_WriteCommand(0x14); // 修复缺少分号 - OLED_WriteCommand(0xAF); // 打开显示 -} - -void OLED_Clear(void) { - memset(oled_buffer, 0, sizeof(oled_buffer)); - dirty_rect.x_min = 0; - dirty_rect.x_max = OLED_WIDTH - 1; - dirty_rect.y_min = 0; - dirty_rect.y_max = OLED_HEIGHT - 1; - dirty_rect.dirty = 1; - OLED_UpdateScreen(); -} - -void OLED_UpdateScreen(void) { - OLED_UpdateDirtyScreen(); -} - -void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color) { - if (x >= OLED_WIDTH || y >= OLED_HEIGHT) return; - - if (color) { - if (!(oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8)))) { - oled_buffer[x + (y / 8) * OLED_WIDTH] |= (1 << (y % 8)); - OLED_MarkDirty(x, y); - } - } else { - if (oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8))) { - oled_buffer[x + (y / 8) * OLED_WIDTH] &= ~(1 << (y % 8)); - OLED_MarkDirty(x, y); - } - } -} - -void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color) { - if (ch < ' ' || ch > '~') return; - - if (x >= OLED_WIDTH || y >= OLED_HEIGHT || x + 8 > OLED_WIDTH || y + 8 > OLED_HEIGHT) { - return; - } - - const uint8_t *font_data = oled_font[ch - ' ']; - - for (uint8_t i = 0; i < 8; i++) { - uint8_t column_data = font_data[i]; - for (uint8_t j = 0; j < 8; j++) { - if (column_data & (1 << j)) { - OLED_DrawPixel(x + i, y + j, color); - } else { - OLED_DrawPixel(x + i, y + j, !color); - } - } - } -} - -void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color) { - while (*str) { - OLED_DrawChar(x, y, *str, color); - x += 8; - if (x + 8 > OLED_WIDTH) { - x = 0; - y += 8; - } - if (y + 8 > OLED_HEIGHT) { - break; - } - str++; - } -} - -/* Private functions -------------------------------------------------------- */ - -static void OLED_MarkDirty(uint8_t x, uint8_t y) { - if (!dirty_rect.dirty) { - dirty_rect.x_min = x; - dirty_rect.x_max = x; - dirty_rect.y_min = y; - dirty_rect.y_max = y; - dirty_rect.dirty = 1; - } else { - if (x < dirty_rect.x_min) dirty_rect.x_min = x; - if (x > dirty_rect.x_max) dirty_rect.x_max = x; - if (y < dirty_rect.y_min) dirty_rect.y_min = y; - if (y > dirty_rect.y_max) dirty_rect.y_max = y; - } -} - -static void OLED_UpdateDirtyScreen(void) { - if (!dirty_rect.dirty) return; - - uint8_t y_start = dirty_rect.y_min / 8; - uint8_t y_end = dirty_rect.y_max / 8; - - for (uint8_t i = y_start; i <= y_end; i++) { - OLED_WriteCommand(0xB0 + i); - OLED_WriteCommand(dirty_rect.x_min & 0x0F); - OLED_WriteCommand(0x10 | (dirty_rect.x_min >> 4)); - uint8_t width = dirty_rect.x_max - dirty_rect.x_min + 1; - OLED_WriteData(&oled_buffer[dirty_rect.x_min + i * OLED_WIDTH], width); - } - - dirty_rect.dirty = 0; -} diff --git a/assets/User_code/device/oled_i2c.h b/assets/User_code/device/oled_i2c.h deleted file mode 100644 index 4958802..0000000 --- a/assets/User_code/device/oled_i2c.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ----------------------------------------------------------------- */ -#include - -/* Exported constants ------------------------------------------------------- */ -#define OLED_COLOR_BLACK 0 -#define OLED_COLOR_WHITE 1 - -/* Exported functions prototypes -------------------------------------------- */ -void OLED_Init(void); -void OLED_Clear(void); -void OLED_UpdateScreen(void); -void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color); -void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color); -void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color); -void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t index); - - -#ifdef __cplusplus -} -#endif diff --git a/assets/User_code/device/pc_uart.c b/assets/User_code/device/pc_uart.c deleted file mode 100644 index eaedcbd..0000000 --- a/assets/User_code/device/pc_uart.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "pc_uart.h" - -#include - -#include "bsp\uart.h" -#include "device.h" - -#define UART_HANDLE BSP_UART_GetHandle(BSP_UART_PC) - -#define AI_LEN_RX_BUFF (sizeof(UART_RxData_t)) - -static bool rx_flag = false; - -static uint8_t rxbuf[AI_LEN_RX_BUFF]; - -static void UART_RxCpltCallback(void) { rx_flag = true; } - -int UART_Init(UART_t *huart) -{ - UNUSED(huart); - //注册回调函数 - HAL_UART_RegisterCallback(UART_HANDLE, BSP_UART_RX_CPLT_CB, UART_RxCpltCallback); - return DEVICE_OK -} - -int UART_StartReceive(UART_t *huart) -{ - UNUSED(huart); - HAL_UART_Receive_DMA(UART_HANDLE, rxbuf, AI_LEN_RX_BUFF); - return DEVICE_OK; -} - -bool UART_IsReceiveComplete(void) -{ - return rx_flag; -} - -int8_t UART_ParseData(UART_t *huart) -{ - - memcpy(&huart->rx_data, rxbuf, sizeof(UART_RxData_t)); -} - -void UART_PackTx(UART_t *huart, UART_TxData_t *tx_data) -{ - memcpy(tx_data, huart->tx_data, sizeof(UART_TxData_t)); -} - -int8_t UART_StartSend(UART_t *huart) -{ - if (HAL_UART_Transmit_DMA(UART_HANDLE, huart->tx_data, sizeof(UART_TxData_t)) == HAL_OK) - { - return DEVICE_OK - } - return DEVICE_ERR; -} \ No newline at end of file diff --git a/assets/User_code/device/pc_uart.h b/assets/User_code/device/pc_uart.h deleted file mode 100644 index 683eed4..0000000 --- a/assets/User_code/device/pc_uart.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - UART通讯模板 -*/ - -#pragma once - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Includes ----------------------------------------------------------------- */ -#include -#include - -/* Exported constants ------------------------------------------------------- */ -/* Exported macro ----------------------------------------------------------- */ -/* Exported types ----------------------------------------------------------- */ - -typedef struct -{ - uint8_t head; - uint8_t data; - uint8_t crc; -} UART_RxData_t; - -typedef struct -{ - uint8_t head; - uint8_t data; - uint8_t crc; -} UART_TxData_t; - -typedef struct -{ - UART_RxData_t rx_data; // Received data buffer - UART_TxData_t tx_data; // Transmit data buffer -} UART_t; - -/* Exported functions prototypes -------------------------------------------- */ - -int UART_Init(UART_t *huart); -int UART_StartReceive(UART_t *huart); -bool UART_IsReceiveComplete(void); -int8_t UART_ParseData(UART_t *huart); -void UART_PackTx(UART_t *huart, UART_TxData_t *tx_data); -int8_t UART_StartSend(UART_t *huart); -#ifdef __cplusplus -} -#endif diff --git a/assets/User_code/device/servo.c b/assets/User_code/device/servo.c deleted file mode 100644 index 12841fe..0000000 --- a/assets/User_code/device/servo.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "main.h" -#include "servo.h" - -#include "bsp/servo_pwm.h" - - -/* Private define ----------------------------------------------------------- */ -#define MIN_CYCLE 0.5f //change begin -#define MAX_CYCLE 2.5f -#define ANGLE_LIMIT 180 //change end -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -/* Exported functions ------------------------------------------------------- */ -int serve_Init(BSP_PWM_Channel_t ch) -{ - if(BSP_PWM_Start(ch)!=0){ - return -1; - }else return 0; -} - - -int set_servo_angle(BSP_PWM_Channel_t ch,float angle) -{ - if (angle < 0.0f || angle > ANGLE_LIMIT) { - return -1; // ЧĽǶ - } - - float duty_cycle=MIN_CYCLE+(MAX_CYCLE-MIN_CYCLE)*(angle/ANGLE_LIMIT); - if(BSP_PWM_Set(ch,duty_cycle)!=0){ - return -1; - }else return 0; -} - diff --git a/assets/User_code/device/servo.h b/assets/User_code/device/servo.h deleted file mode 100644 index 97337df..0000000 --- a/assets/User_code/device/servo.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ----------------------------------------------------------------- */ -#include -#include "tim.h" -#include "bsp/bsp.h" -#include "bsp/servo_pwm.h" -/* Exported constants ------------------------------------------------------- */ -/* Exported macro ----------------------------------------------------------- */ -/* Exported types ----------------------------------------------------------- */ - - - -extern int serve_Init(BSP_PWM_Channel_t ch); -extern int set_servo_angle(BSP_PWM_Channel_t ch,float angle); - - - - - - - - - - - - - - -#ifdef __cplusplus -} -#endif - - - - - diff --git a/gpio.c b/gpio.c new file mode 100644 index 0000000..2c00ec4 --- /dev/null +++ b/gpio.c @@ -0,0 +1,93 @@ +/* Includes ----------------------------------------------------------------- */ +#include "bsp/gpio.h" + +#include +#include + +/* Private define ----------------------------------------------------------- */ +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +typedef struct { + uint16_t pin; + GPIO_TypeDef *gpio; +} BSP_GPIO_MAP_t; + +/* Private variables -------------------------------------------------------- */ +static const BSP_GPIO_MAP_t GPIO_Map[BSP_GPIO_NUM] = { + {ACCL_CS_Pin, ACCL_CS_GPIO_Port}, + {GYRO_CS_Pin, GYRO_CS_GPIO_Port}, + {ACCL_INT_Pin, ACCL_INT_GPIO_Port}, + {GYRO_INT_Pin, GYRO_INT_GPIO_Port}, + {USER_KEY_Pin, USER_KEY_GPIO_Port}, +}; + +static void (*GPIO_Callback[16])(void); + +/* Private function -------------------------------------------------------- */ +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + for (uint8_t i = 0; i < 16; i++) { + if (GPIO_Pin & (1 << i)) { + if (GPIO_Callback[i]) { + GPIO_Callback[i](); + } + } + } +} + +/* Exported functions ------------------------------------------------------- */ +int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)) { + if (callback == NULL) return BSP_ERR_NULL; + + for (uint8_t i = 0; i < 16; i++) { + if (pin & (1 << i)) { + GPIO_Callback[i] = callback; + break; + } + } + return BSP_OK; +} + +int8_t BSP_GPIO_EnableIRQ(uint16_t pin) { + switch (pin) { + case BSP_GPIO_IMU_ACCL_CS: + HAL_NVIC_EnableIRQ(ACCL_INT_EXTI_IRQn); + break; + case BSP_GPIO_IMU_GYRO_CS: + HAL_NVIC_EnableIRQ(GYRO_INT_EXTI_IRQn); + break; + default: + return BSP_ERR; + } + return BSP_OK; +} + +int8_t BSP_GPIO_DisableIRQ(uint16_t pin) { + switch (pin) { + case BSP_GPIO_IMU_ACCL_INT: + HAL_NVIC_DisableIRQ(ACCL_INT_EXTI_IRQn); + break; + case BSP_GPIO_IMU_GYRO_INT: + HAL_NVIC_DisableIRQ(GYRO_INT_EXTI_IRQn); + break; + default: + return BSP_ERR; + } + return BSP_OK; +} + +int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value){ + if (gpio >= BSP_GPIO_NUM) return BSP_ERR; + HAL_GPIO_WritePin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin, value); + return BSP_OK; +} + +int8_t BSP_GPIO_TogglePin(BSP_GPIO_t gpio){ + if (gpio >= BSP_GPIO_NUM) return BSP_ERR; + HAL_GPIO_TogglePin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin); + return BSP_OK; +} + +bool BSP_GPIO_ReadPin(BSP_GPIO_t gpio){ + if (gpio >= BSP_GPIO_NUM) return false; + return HAL_GPIO_ReadPin(GPIO_Map[gpio].gpio, GPIO_Map[gpio].pin) == GPIO_PIN_SET; +} diff --git a/gpio.h b/gpio.h new file mode 100644 index 0000000..3ad4f46 --- /dev/null +++ b/gpio.h @@ -0,0 +1,39 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include +#include + +#include "bsp/bsp.h" + +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +typedef enum { + BSP_GPIO_IMU_ACCL_CS, + BSP_GPIO_IMU_GYRO_CS, + BSP_GPIO_IMU_ACCL_INT, + BSP_GPIO_IMU_GYRO_INT, + BSP_GPIO_USER_KEY, + BSP_GPIO_NUM, + BSP_GPIO_ERR, +} BSP_GPIO_t; + +/* Exported functions prototypes -------------------------------------------- */ +int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)); + +int8_t BSP_GPIO_EnableIRQ(uint16_t pin); +int8_t BSP_GPIO_DisableIRQ(uint16_t pin); + +int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value); +int8_t BSP_GPIO_TogglePin(BSP_GPIO_t gpio); + +bool BSP_GPIO_ReadPin(BSP_GPIO_t gpio); + +#ifdef __cplusplus +} +#endif