mirror of
https://github.com/goldenfishs/MRobot.git
synced 2025-09-14 12:54:33 +08:00
疯狂写bsp
This commit is contained in:
parent
d99e9e1ec8
commit
50cfcb0693
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,5 +1,7 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"user_math.h": "c"
|
||||
"user_math.h": "c",
|
||||
"bsp.h": "c",
|
||||
"stdint.h": "c"
|
||||
}
|
||||
}
|
Binary file not shown.
@ -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__()
|
||||
|
@ -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
|
||||
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
|
BIN
assets/User_code/bsp/.DS_Store
vendored
BIN
assets/User_code/bsp/.DS_Store
vendored
Binary file not shown.
@ -1,19 +1,106 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp\can.h"
|
||||
#include "bsp/can.h"
|
||||
#include "bsp/bsp.h"
|
||||
#include <can.h>
|
||||
#include <cmsis_os.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,14 @@ extern "C" {
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <can.h>
|
||||
|
||||
#include "bsp/bsp.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <cmsis_os.h>
|
||||
|
||||
/* 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 */
|
@ -3,4 +3,5 @@ can,要求开启can的中断要求开启can的中断要求开启can的中断要
|
||||
gpio,要求设置label开启中断
|
||||
spi,要求开启spi中断
|
||||
i2c,要求开始spi中断
|
||||
mm,这是套了一层的内存
|
||||
mm,这是套了一层的内存
|
||||
time,需要使用开启freerots
|
|
@ -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;
|
||||
}
|
@ -6,18 +6,30 @@ extern "C" {
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
@ -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);
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ extern "C" {
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <i2c.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
||||
|
70
assets/User_code/bsp/pwm.c
Normal file
70
assets/User_code/bsp/pwm.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp/pwm.h"
|
||||
#include "bsp.h"
|
||||
|
||||
#include <tim.h>
|
||||
|
||||
/* 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;
|
||||
}
|
30
assets/User_code/bsp/pwm.h
Normal file
30
assets/User_code/bsp/pwm.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
@ -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);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ extern "C" {
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <spi.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
@ -1,16 +1,35 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp/delay.h"
|
||||
#include "bsp.h"
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
#include <main.h>
|
||||
|
||||
#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")));
|
@ -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
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp\uart.h"
|
||||
#include <uart.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ extern "C" {
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <usart.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
@ -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
|
|
BIN
assets/User_code/device/.DS_Store
vendored
BIN
assets/User_code/device/.DS_Store
vendored
Binary file not shown.
@ -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;
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#ifndef KEY_GPIO_H
|
||||
#define KEY_GPIO_H
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
#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
|
381
assets/User_code/device/oled.c
Normal file
381
assets/User_code/device/oled.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
OLED显示模块。
|
||||
|
||||
使用SPI通信时,需要#define OLED_USE_SPI
|
||||
使用I2C通信时,需要#define OLED_USE_I2C
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
/* Include 自身的头文件。*/
|
||||
#include "oled.h"
|
||||
|
||||
/* Include 标准库。*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Include HAL相关的头文件。*/
|
||||
#include "bsp_delay.h"
|
||||
#include "bsp_spi.h"
|
||||
#include <gpio.h>
|
||||
|
||||
#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;
|
||||
}
|
45
assets/User_code/device/oled.h
Normal file
45
assets/User_code/device/oled.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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
|
@ -1,267 +0,0 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "device/oled_i2c.h"
|
||||
#include "bsp/i2c.h"
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
/* 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;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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
|
@ -1,57 +0,0 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "pc_uart.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
UART通讯模板
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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
|
@ -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;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
#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
|
||||
|
||||
|
||||
|
||||
|
||||
|
93
gpio.c
Normal file
93
gpio.c
Normal file
@ -0,0 +1,93 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp/gpio.h"
|
||||
|
||||
#include <gpio.h>
|
||||
#include <main.h>
|
||||
|
||||
/* 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;
|
||||
}
|
39
gpio.h
Normal file
39
gpio.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
Loading…
Reference in New Issue
Block a user