[feat] add ate

This commit is contained in:
zhji 2025-10-06 17:55:08 +08:00
parent 8c5616fbce
commit c1e34d2038
30 changed files with 2541 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
bootloader/build/*
lark1fq/build/*
ate/build/*
test/build/*
tools/*.exe
tools/*.xls

87
ate/CMakeLists.txt Executable file
View File

@ -0,0 +1,87 @@
cmake_minimum_required(VERSION 3.10)
set(PROJ_NAME "lark1fq")
set(BIN_FILE ${PROJ_NAME}.bin)
set(ASM_FILE ${PROJ_NAME}.asm)
project(${PROJ_NAME} VERSION 0.1)
# toolchain path
set(TOOLCHAIN "arm-none-eabi-")
set(CMAKE_C_COMPILER "${TOOLCHAIN}gcc")
set(CMAKE_ASM_COMPILER "${TOOLCHAIN}gcc")
set(CMAKE_OBJCOPY "${TOOLCHAIN}objcopy")
set(CMAKE_OBJDUMP "${TOOLCHAIN}objdump")
set(CMAKE_AR "${TOOLCHAIN}ar")
set(CMAKE_RANLIB "${TOOLCHAIN}ranlib")
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/flash.ld")
set(CMAKE_C_FLAGS " \
-mcpu=cortex-m4 \
-mthumb \
-g3 \
-O2 \
-Wall \
-nostartfiles \
-mfloat-abi=hard \
-mfpu=vfpv4-d16 \
-ffunction-sections \
-fdata-sections \
")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS " \
-ffunction-sections \
-fdata-sections \
-Wl,--gc-sections \
-T${LINKER_SCRIPT} \
-Wl,-Map=${PROJ_NAME}.map \
--specs=nano.specs \
-Wl,--print-memory-usage \
-Wl,--print-output-format \
")
add_definitions(-DSTM32F40_41xxx)
add_definitions(-DUSE_STDPERIPH_DRIVER)
enable_language(ASM)
add_executable(${PROJ_NAME}.elf main.c)
target_sources(${PROJ_NAME}.elf PUBLIC ${CMAKE_CURRENT_LIST_DIR}/start.S)
add_subdirectory(../driver driver)
target_link_libraries(${PROJ_NAME}.elf driver)
target_include_directories(${PROJ_NAME}.elf PUBLIC ../driver/stddriver/inc)
target_include_directories(${PROJ_NAME}.elf PUBLIC ../driver/cmsis/inc)
add_subdirectory(../component/fatfs component/fatfs)
target_link_libraries(${PROJ_NAME}.elf fatfs)
add_subdirectory(src src)
target_link_libraries(${PROJ_NAME}.elf src)
target_include_directories(${PROJ_NAME}.elf PUBLIC src)
target_link_libraries(${PROJ_NAME}.elf m) # math library
add_custom_command(TARGET ${PROJ_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJ_NAME}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} -d -S $<TARGET_FILE:${PROJ_NAME}.elf> >${ASM_FILE}
# COMMENT "Generate ${BIN_FILE}\r\n"
COMMAND size ${PROJ_NAME}.elf
COMMAND echo "Calculating SHA-256 checksum for ${BIN_FILE}:"
COMMAND sha256sum ${BIN_FILE}
)
# get git tag
execute_process(
COMMAND git describe --abbrev=40 --tags --dirty --always
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(GIT_TAG)
set(PROJECT_SDK_VERSION ${GIT_TAG})
else()
message(WARNING "No Valid version info found for SDK!")
set(PROJECT_SDK_VERSION "version-unknown-panic")
endif()
message(STATUS "Project SDK Version: ${PROJECT_SDK_VERSION}")

18
ate/Makefile Normal file
View File

@ -0,0 +1,18 @@
CMAKE = cmake # use user cmake
cmake_generator = "Unix Makefiles"
RM = $(CMAKE) -E remove_directory
MAKEFLAGS += --no-print-directory
TOOLCHAIN ?= arm-none-eabi-
#cmake definition config
cmake_definition+= -DTOOLCHAIN=${TOOLCHAIN}
build:Makefile
$(CMAKE) -S . -B build -G $(cmake_generator) $(cmake_definition)
$(MAKE) -C build -j
clean::
$(RM) build
.PHONY:build clean

80
ate/flash.ld Executable file
View File

@ -0,0 +1,80 @@
ENTRY(Reset_Handler)
StackSize = 0x4000; /* 16KB */
MEMORY
{
FLASH (rx) :ORIGIN = 0x08020000, LENGTH = 384K
RAM (xrw) :ORIGIN = 0x20000000, LENGTH = 112K
CCM (rw) :ORIGIN = 0x10000000, LENGTH = 64K - StackSize
}
_stack_top = ORIGIN(CCM) + LENGTH(CCM) + StackSize;
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
. = ALIGN(4);
} >FLASH
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} >FLASH
_data_load = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_data_run = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_data_run_end = .;
} >RAM AT>FLASH
_data_ccm_load = LOADADDR(.data_ccm);
.data_ccm :
{
. = ALIGN(4);
_data_ccm_run = .;
*(.data_ccm)
*(.data_ccm*)
. = ALIGN(4);
_data_ccm_run_end = .;
} >CCM AT>FLASH
.bss (NOLOAD) :
{
. = ALIGN(4);
_bss_run = .;
*(.bss)
*(.bss.*)
. = ALIGN(4);
_bss_run_end = .;
} >RAM
.bss_ccm (NOLOAD) :
{
. = ALIGN(4);
_bss_ccm_run = .;
*(.bss_ccm)
*(.bss_ccm.*)
. = ALIGN(4);
_bss_ccm_run_end = .;
} >CCM
}

55
ate/main.c Executable file
View File

@ -0,0 +1,55 @@
#include "led.h"
#include "button.h"
#include "heat.h"
#include "ltc1867.h"
#include "modbus.h"
#include "ltc2640.h"
#include "calc.h"
#include "sd.h"
#include "stm32f4xx_rcc.h"
uint32_t system_tick_cnt;
void system_tick_init(void)
{
RCC_ClocksTypeDef rcc_clocks;
system_tick_cnt = 0;
RCC_GetClocksFreq(&rcc_clocks);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
SysTick_Config(rcc_clocks.HCLK_Frequency / 1000);
}
void system_init(void)
{
led_init(LED1 | LED2);
button_init();
heat_init();
ltc1867_init();
modbus_init();
system_tick_init();
ltc2640_init();
}
int main(void)
{
system_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
SCB->VTOR = 0x08020000;
__enable_irq();
while (1) {
modbus_loop();
led_loop();
button_loop();
heat_loop();
ltc2640_loop();
calc_loop();
sd_loop();
}
return 0;
}
void SysTick_Handler(void)
{
system_tick_cnt++;
}

576
ate/script/ate.py Normal file
View File

@ -0,0 +1,576 @@
import tkinter as tk
from tkinter import ttk, messagebox
import serial
import serial.tools.list_ports
import threading
import time
from datetime import datetime
import crcmod
class ATEApplication:
def __init__(self, root):
self.root = root
self.root.title("LARK-1FQ ATE设备监控")
self.root.geometry("680x480")
# 串口相关变量
self.serial_port = None
self.is_connected = False
self.read_thread = None
self.stop_thread = False
self.receive_buffer = bytearray() # 接收缓冲区
# 创建CRC计算函数
self.crc16_func = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
# 数据存储
self.frequency_values = [0, 0, 0, 0] # ch0-ch3 频率值
self.peak_values = [0, 0, 0, 0] # ch0-ch3 峰峰值
self.key_status = 0 # 按键状态
self.sd_status = 0 # SD卡状态
# 上下限设置
self.freq_limits = [
{"min": 7, "max": 9}, # ch0
{"min": 7, "max": 9}, # ch1
{"min": 7, "max": 9}, # ch2
{"min": 7, "max": 9} # ch3
]
self.peak_limits = [
{"min": 2000, "max": 4000}, # ch0
{"min": 2000, "max": 4000}, # ch1
{"min": 2000, "max": 4000}, # ch2
{"min": 2000, "max": 4000} # ch3
]
self.create_widgets()
self.refresh_ports()
# 设置关闭事件
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
def create_widgets(self):
# 1. 串口相关界面
serial_frame = ttk.LabelFrame(self.root, text="串口设置", padding=10)
serial_frame.pack(fill="x", padx=10, pady=5)
# 串口号选择
ttk.Label(serial_frame, text="串口号:").grid(row=0, column=0, padx=5)
self.port_var = tk.StringVar()
self.port_combobox = ttk.Combobox(serial_frame, textvariable=self.port_var, width=15)
self.port_combobox.grid(row=0, column=1, padx=5)
self.refresh_btn = ttk.Button(serial_frame, text="刷新", command=self.refresh_ports)
self.refresh_btn.grid(row=0, column=2, padx=5)
# 波特率选择
ttk.Label(serial_frame, text="波特率:").grid(row=0, column=3, padx=5)
self.baud_var = tk.StringVar(value="19200")
baud_combobox = ttk.Combobox(serial_frame, textvariable=self.baud_var,
values=["9600", "19200", "38400", "57600", "115200"], width=10)
baud_combobox.grid(row=0, column=4, padx=5)
# 打开关闭按钮
self.open_btn = ttk.Button(serial_frame, text="打开串口", command=self.open_serial)
self.open_btn.grid(row=0, column=5, padx=5)
self.close_btn = ttk.Button(serial_frame, text="关闭串口", command=self.close_serial, state="disabled")
self.close_btn.grid(row=0, column=6, padx=5)
# 调试信息显示
self.debug_var = tk.StringVar(value="等待连接...")
debug_label = ttk.Label(serial_frame, textvariable=self.debug_var, foreground="blue")
debug_label.grid(row=1, column=0, columnspan=7, pady=5)
# 2. 数值比较界面
value_frame = ttk.LabelFrame(self.root, text="数值比较", padding=10)
value_frame.pack(fill="both", expand=True, padx=10, pady=5)
# 频率部分(左边)
freq_frame = ttk.LabelFrame(value_frame, text="频率 (Hz)")
freq_frame.pack(side="left", fill="both", expand=True, padx=5)
self.freq_widgets = []
for i in range(4):
ch_frame = ttk.Frame(freq_frame)
ch_frame.pack(fill="x", pady=2)
ttk.Label(ch_frame, text=f"CH{i}:").pack(side="left")
# 最小值输入
min_frame = ttk.Frame(ch_frame)
min_frame.pack(side="left", padx=2)
ttk.Label(min_frame, text="min:").pack()
min_var = tk.StringVar(value="7")
min_entry = tk.Entry(min_frame, textvariable=min_var, width=5, bg="white")
min_entry.pack()
min_entry.bind('<Return>', lambda e, ch=i: self.update_freq_limit(ch))
# 当前值显示
value_label = tk.Label(ch_frame, text="0.0", width=8, relief="sunken", bg="white")
value_label.pack(side="left", padx=5)
# 最大值输入
max_frame = ttk.Frame(ch_frame)
max_frame.pack(side="left", padx=2)
ttk.Label(max_frame, text="max:").pack()
max_var = tk.StringVar(value="9")
max_entry = tk.Entry(max_frame, textvariable=max_var, width=5, bg="white")
max_entry.pack()
max_entry.bind('<Return>', lambda e, ch=i: self.update_freq_limit(ch))
self.freq_widgets.append({
"min_var": min_var,
"max_var": max_var,
"min_entry": min_entry,
"max_entry": max_entry,
"value_label": value_label
})
# 峰峰值部分(右边)
peak_frame = ttk.LabelFrame(value_frame, text="峰峰值 (mV)")
peak_frame.pack(side="right", fill="both", expand=True, padx=5)
self.peak_widgets = []
for i in range(4):
ch_frame = ttk.Frame(peak_frame)
ch_frame.pack(fill="x", pady=2)
ttk.Label(ch_frame, text=f"CH{i}:").pack(side="left")
# 最小值输入
min_frame = ttk.Frame(ch_frame)
min_frame.pack(side="left", padx=2)
ttk.Label(min_frame, text="min:").pack()
min_var = tk.StringVar(value="2000")
min_entry = tk.Entry(min_frame, textvariable=min_var, width=5, bg="white")
min_entry.pack()
min_entry.bind('<Return>', lambda e, ch=i: self.update_peak_limit(ch))
# 当前值显示
value_label = tk.Label(ch_frame, text="0", width=8, relief="sunken", bg="white")
value_label.pack(side="left", padx=5)
# 最大值输入
max_frame = ttk.Frame(ch_frame)
max_frame.pack(side="left", padx=2)
ttk.Label(max_frame, text="max:").pack()
max_var = tk.StringVar(value="4000")
max_entry = tk.Entry(max_frame, textvariable=max_var, width=5, bg="white")
max_entry.pack()
max_entry.bind('<Return>', lambda e, ch=i: self.update_peak_limit(ch))
self.peak_widgets.append({
"min_var": min_var,
"max_var": max_var,
"min_entry": min_entry,
"max_entry": max_entry,
"value_label": value_label
})
# 3. 状态显示界面
status_frame = ttk.LabelFrame(self.root, text="状态显示", padding=10)
status_frame.pack(fill="x", padx=10, pady=5)
# 通讯状态
comm_frame = ttk.Frame(status_frame)
comm_frame.pack(side="left", expand=True)
ttk.Label(comm_frame, text="通讯状态:").pack()
self.comm_status = tk.Label(comm_frame, text="", font=("Arial", 20), fg="red")
self.comm_status.pack()
# SD卡状态
sd_frame = ttk.Frame(status_frame)
sd_frame.pack(side="left", expand=True)
ttk.Label(sd_frame, text="SD卡状态:").pack()
self.sd_status_label = tk.Label(sd_frame, text="", font=("Arial", 20), fg="red")
self.sd_status_label.pack()
# 按键状态
key_frame = ttk.Frame(status_frame)
key_frame.pack(side="left", expand=True)
ttk.Label(key_frame, text="按键状态:").pack()
self.key_status_label = tk.Label(key_frame, text="", font=("Arial", 20), fg="red")
self.key_status_label.pack()
def refresh_ports(self):
"""刷新可用串口列表"""
ports = serial.tools.list_ports.comports()
port_list = [port.device for port in ports]
self.port_combobox['values'] = port_list
if port_list and not self.port_var.get():
self.port_var.set(port_list[0])
def open_serial(self):
"""打开串口"""
port = self.port_var.get()
baudrate = self.baud_var.get()
if not port:
messagebox.showerror("错误", "请选择串口号")
return
try:
self.serial_port = serial.Serial(
port=port,
baudrate=int(baudrate),
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1
)
# 清空缓冲区
self.clear_serial_buffer()
self.receive_buffer = bytearray()
self.is_connected = True
self.open_btn.config(state="disabled")
self.close_btn.config(state="normal")
self.refresh_btn.config(state="disabled")
# 启动读取线程
self.stop_thread = False
self.read_thread = threading.Thread(target=self.serial_read_loop)
self.read_thread.daemon = True
self.read_thread.start()
self.update_debug_info("串口打开成功,开始发送查询命令...")
messagebox.showinfo("成功", "串口打开成功")
except Exception as e:
messagebox.showerror("错误", f"打开串口失败: {str(e)}")
def close_serial(self):
"""关闭串口"""
self.stop_thread = True
self.is_connected = False
if self.serial_port and self.serial_port.is_open:
self.serial_port.close()
self.open_btn.config(state="normal")
self.close_btn.config(state="disabled")
self.refresh_btn.config(state="normal")
self.comm_status.config(fg="red")
self.update_debug_info("串口已关闭")
def clear_serial_buffer(self):
"""清空串口缓冲区"""
if self.serial_port and self.serial_port.is_open:
try:
self.serial_port.reset_input_buffer()
self.serial_port.reset_output_buffer()
self.receive_buffer.clear()
self.update_debug_info("串口缓冲区已清空")
except Exception as e:
self.update_debug_info(f"清空缓冲区错误: {e}")
def update_debug_info(self, message):
"""更新调试信息"""
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
debug_msg = f"[{timestamp}] {message}"
self.debug_var.set(debug_msg)
print(debug_msg)
def calculate_crc(self, data):
"""计算CRC并返回对调后的两个字节"""
if not data:
return bytes.fromhex('0000')
# 计算CRC
crc_value = self.crc16_func(data)
# 转换为两个字节并对调
crc_bytes = crc_value.to_bytes(2, byteorder='big')
crc_swapped = bytes([crc_bytes[1], crc_bytes[0]])
return crc_swapped
def send_and_receive_command(self):
"""发送命令并接收响应"""
if not (self.serial_port and self.serial_port.is_open):
return
try:
# 清空接收缓冲区
self.clear_serial_buffer()
# 发送查询命令
full_command = bytes.fromhex('5A04123400097991')
self.serial_port.write(full_command)
self.update_debug_info(f"发送命令: {full_command.hex().upper()}")
# 等待100ms让设备准备响应
time.sleep(0.1)
# 读取响应数据
if self.serial_port.in_waiting:
data = self.serial_port.read(self.serial_port.in_waiting)
if data:
self.update_debug_info(f"收到 {len(data)} 字节响应数据")
self.process_received_data(data)
else:
self.update_debug_info("未收到响应数据")
self.root.after(0, lambda: self.comm_status.config(fg="red"))
else:
self.update_debug_info("无响应数据可读")
self.root.after(0, lambda: self.comm_status.config(fg="red"))
except Exception as e:
self.update_debug_info(f"发送接收命令错误: {e}")
self.root.after(0, lambda: self.comm_status.config(fg="red"))
def serial_read_loop(self):
"""串口读取循环"""
last_send_time = 0
send_interval = 0.2 # 200ms发送一次
while self.is_connected and not self.stop_thread:
current_time = time.time()
# 发送并接收命令
if current_time - last_send_time >= send_interval:
self.send_and_receive_command()
last_send_time = current_time
time.sleep(0.01)
def process_received_data(self, data):
"""处理接收到的数据"""
hex_data = data.hex().upper()
self.update_debug_info(f"原始响应数据: {hex_data}")
# 检查数据长度
if len(data) < 23:
self.update_debug_info(f"数据长度不足: {len(data)}字节期望至少23字节")
return
# 查找帧头
frame_start = -1
for i in range(len(data) - 2):
if data[i] == 0x5A and data[i+1] == 0x04 and data[i+2] == 0x12:
frame_start = i
break
if frame_start == -1:
self.update_debug_info("未找到帧头 5A0412")
return
self.update_debug_info(f"找到帧头,位置: {frame_start}")
# 提取完整帧从帧头开始的23字节
if len(data) - frame_start >= 23:
frame_data = data[frame_start:frame_start+23]
self.process_received_frame(frame_data)
else:
self.update_debug_info("帧数据不完整")
def process_received_frame(self, data):
"""处理接收到的完整数据帧23字节"""
hex_data = data.hex().upper()
self.update_debug_info(f"处理数据帧: {hex_data}")
# CRC校验 - 前21字节计算CRC最后2字节是CRC
if not self.check_crc(data):
self.update_debug_info("CRC校验失败")
self.root.after(0, lambda: self.comm_status.config(fg="red"))
return
# 解析数据
try:
# 解析峰峰值 (4个通道每个2字节)
peak_values = []
for i in range(4):
start_idx = 3 + i * 2 # 跳过帧头5A0412 (3字节)
peak_value = (data[start_idx] << 8) | data[start_idx + 1]
peak_values.append(peak_value)
# 解析频率 (4个通道每个2字节需要除以10)
freq_values = []
for i in range(4):
start_idx = 11 + i * 2 # 峰峰值后是频率
freq_value = (data[start_idx] << 8) | data[start_idx + 1]
freq_values.append(freq_value / 10.0)
# 解析状态
key_status = data[19] # 按键状态
sd_status = data[20] # SD卡状态
self.update_debug_info(f"解析成功: 峰峰值{peak_values}, 频率{freq_values}, 按键{key_status}, SD卡{sd_status}")
# 更新界面
self.root.after(0, self.update_display, peak_values, freq_values, key_status, sd_status)
# 通讯成功,更新状态
self.root.after(0, lambda: self.comm_status.config(fg="green"))
except Exception as e:
self.update_debug_info(f"解析数据错误: {e}")
self.root.after(0, lambda: self.comm_status.config(fg="red"))
def check_crc(self, data):
"""CRC校验 - 前21字节计算CRC最后2字节是CRC需要对调"""
try:
if len(data) < 23:
return False
# 分离数据前21字节和CRC最后2字节
data_part = data[:21] # 前21字节是数据
crc_received = data[21:23] # 最后2字节是CRC
# 计算期望的CRC值对调后的
expected_crc = self.calculate_crc(data_part)
# 比较CRC
result = crc_received == expected_crc
if not result:
self.update_debug_info(f"CRC不匹配: 收到{crc_received.hex().upper()}, 期望{expected_crc.hex().upper()}")
return result
except Exception as e:
self.update_debug_info(f"CRC校验错误: {e}")
return False
def update_display(self, peak_values, freq_values, key_status, sd_status):
"""更新显示"""
# 更新峰峰值
for i in range(4):
value = peak_values[i]
self.peak_values[i] = value
widget = self.peak_widgets[i]
widget["value_label"].config(text=str(value))
# 检查范围并设置颜色
in_range = self.peak_limits[i]["min"] <= value <= self.peak_limits[i]["max"]
color = "green" if in_range else "red"
widget["value_label"].config(bg=color)
# 如果越界,设置上下限输入框颜色
min_color = "red" if value < self.peak_limits[i]["min"] else "white"
max_color = "red" if value > self.peak_limits[i]["max"] else "white"
widget["min_entry"].config(bg=min_color)
widget["max_entry"].config(bg=max_color)
# 更新频率
for i in range(4):
value = freq_values[i]
self.frequency_values[i] = value
widget = self.freq_widgets[i]
widget["value_label"].config(text=f"{value:.1f}")
# 检查范围并设置颜色
in_range = self.freq_limits[i]["min"] <= value <= self.freq_limits[i]["max"]
color = "green" if in_range else "red"
widget["value_label"].config(bg=color)
# 如果越界,设置上下限输入框颜色
min_color = "red" if value < self.freq_limits[i]["min"] else "white"
max_color = "red" if value > self.freq_limits[i]["max"] else "white"
widget["min_entry"].config(bg=min_color)
widget["max_entry"].config(bg=max_color)
# 更新状态
self.key_status = key_status
self.sd_status = sd_status
# 按键状态0=未按下1=按下
key_color = "green" if key_status == 1 else "red"
self.key_status_label.config(fg=key_color)
# SD卡状态5=成功,其他=失败
sd_color = "green" if sd_status == 5 else "red"
self.sd_status_label.config(fg=sd_color)
self.update_debug_info("界面更新完成")
def update_freq_limit(self, channel):
"""更新频率上下限"""
try:
min_val = float(self.freq_widgets[channel]["min_var"].get())
max_val = float(self.freq_widgets[channel]["max_var"].get())
# 验证最小值不大于最大值
if min_val > max_val:
messagebox.showerror("错误", "最小值不能大于最大值")
return
self.freq_limits[channel]["min"] = min_val
self.freq_limits[channel]["max"] = max_val
# 立即检查当前值并更新显示
self.check_freq_value(channel)
except ValueError:
messagebox.showerror("错误", "请输入有效的数字")
def update_peak_limit(self, channel):
"""更新峰峰值上下限"""
try:
min_val = float(self.peak_widgets[channel]["min_var"].get())
max_val = float(self.peak_widgets[channel]["max_var"].get())
# 验证最小值不大于最大值
if min_val > max_val:
messagebox.showerror("错误", "最小值不能大于最大值")
return
self.peak_limits[channel]["min"] = min_val
self.peak_limits[channel]["max"] = max_val
# 立即检查当前值并更新显示
self.check_peak_value(channel)
except ValueError:
messagebox.showerror("错误", "请输入有效的数字")
def check_freq_value(self, channel):
"""检查指定通道的频率值是否在范围内"""
value = self.frequency_values[channel]
widget = self.freq_widgets[channel]
# 检查范围并设置颜色
in_range = self.freq_limits[channel]["min"] <= value <= self.freq_limits[channel]["max"]
color = "green" if in_range else "red"
widget["value_label"].config(bg=color)
# 如果越界,设置上下限输入框颜色
min_color = "red" if value < self.freq_limits[channel]["min"] else "white"
max_color = "red" if value > self.freq_limits[channel]["max"] else "white"
widget["min_entry"].config(bg=min_color)
widget["max_entry"].config(bg=max_color)
def check_peak_value(self, channel):
"""检查指定通道的峰峰值是否在范围内"""
value = self.peak_values[channel]
widget = self.peak_widgets[channel]
# 检查范围并设置颜色
in_range = self.peak_limits[channel]["min"] <= value <= self.peak_limits[channel]["max"]
color = "green" if in_range else "red"
widget["value_label"].config(bg=color)
# 如果越界,设置上下限输入框颜色
min_color = "red" if value < self.peak_limits[channel]["min"] else "white"
max_color = "red" if value > self.peak_limits[channel]["max"] else "white"
widget["min_entry"].config(bg=min_color)
widget["max_entry"].config(bg=max_color)
def check_current_values(self):
"""检查当前值是否在范围内"""
for i in range(4):
self.check_freq_value(i)
self.check_peak_value(i)
def on_closing(self):
"""程序关闭时的清理工作"""
self.stop_thread = True
if self.serial_port and self.serial_port.is_open:
self.serial_port.close()
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
app = ATEApplication(root)
root.mainloop()

4
ate/script/pack_cmd.txt Normal file
View File

@ -0,0 +1,4 @@
python -m PyInstaller --onefile --windowed --name ate ate.py
dependency:
pip install pyinstaller

22
ate/src/CMakeLists.txt Executable file
View File

@ -0,0 +1,22 @@
include_directories(.)
include_directories(../../driver/sdcard)
include_directories(../../driver/stddriver/inc)
include_directories(../../driver/cmsis/inc)
include_directories(../../component/fatfs/inc)
file(GLOB FILELIST
device.c
led.c
button.c
heat.c
ltc1867.c
ltc2640.c
rs485.c
modbus.c
calc.c
sd.c
)
add_library(src STATIC ${FILELIST})
target_link_libraries(src driver)
target_link_libraries(src fatfs)

39
ate/src/button.c Executable file
View File

@ -0,0 +1,39 @@
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "button.h"
#include "device.h"
void button_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = PIN_BUTTON,
.GPIO_Mode = GPIO_Mode_IN,
.GPIO_OType = GPIO_OType_PP,
.GPIO_Speed = GPIO_Speed_2MHz,
.GPIO_PuPd = GPIO_PuPd_UP,
};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_Init(PORT_BUTTON, &GPIO_InitStructure);
}
int button_is_pressed(void)
{
if (GPIO_ReadInputDataBit(PORT_BUTTON, PIN_BUTTON)) {
return 0;
} else {
return 1;
}
}
void button_loop(void)
{
static uint32_t ms = 0;
if (system_tick_cnt < (ms + 100)) {
return;
}
ms = system_tick_cnt;
device_data.button = button_is_pressed() ? 1 : 0;
}

23
ate/src/button.h Executable file
View File

@ -0,0 +1,23 @@
#ifndef __BUTTON_H__
#define __BUTTON_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define PORT_BUTTON (GPIOB)
#define PIN_BUTTON (GPIO_Pin_14)
extern uint32_t system_tick_cnt;
void button_init(void);
int button_is_pressed(void);
void button_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __BUTTON_H__ */

54
ate/src/calc.c Executable file
View File

@ -0,0 +1,54 @@
#include "calc.h"
#include "device.h"
#include "ltc1867.h"
uint16_t calc_freq(uint32_t pre, uint32_t now)
{
uint32_t freq;
if (now > pre) {
freq = now - pre;
} else {
freq = pre - now;
}
freq = (LEDIR_FREQ * SAMPLES_PER_PERIOD * 10 + freq / 2) / freq;
return (uint16_t)freq;
}
uint16_t calc_peak(int ch, uint32_t pre, uint32_t now)
{
uint16_t min, max, val;
min = 65535;
max = 0;
for (uint32_t i = data_ltc1867.sample_pre[ch]; i < data_ltc1867.sample_now[ch]; i++) {
val = data_ltc1867_raw[ch][i % LTC1867_RAW_BUFF_SIZE];
if (min > val) {
min = val;
}
if (max < val) {
max = val;
}
}
return (max - min + 8) / 16;
}
void calc_loop(void)
{
static uint32_t sample_cnt = 0;
static uint32_t pre[LTC1867_CH_CNT] = {0, 0, 0, 0};
if (sample_cnt == data_ltc1867.sample_cnt) {
return;
}
sample_cnt = data_ltc1867.sample_cnt;
for (int i = 0; i < LTC1867_CH_CNT; i++) {
if (pre[i] != data_ltc1867.sample_pre[i]) {
pre[i] = data_ltc1867.sample_pre[i];
device_data.freq[i] = calc_freq(data_ltc1867.sample_pre[i], data_ltc1867.sample_now[i]);
device_data.peak[i] = calc_peak(i, data_ltc1867.sample_pre[i], data_ltc1867.sample_now[i]);
}
}
}

17
ate/src/calc.h Executable file
View File

@ -0,0 +1,17 @@
#ifndef __CALC_H__
#define __CALC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
uint16_t calc_freq(uint32_t pre, uint32_t now);
void calc_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __CALC_H__ */

15
ate/src/config.h Executable file
View File

@ -0,0 +1,15 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
#define LEDIR_FREQ (8)
#define SAMPLES_PER_PERIOD (64)
#ifdef __cplusplus
}
#endif
#endif /* __CONFIG_H__ */

29
ate/src/device.c Executable file
View File

@ -0,0 +1,29 @@
#include "device.h"
#define BITMAP_GAS_ADDR (0x080A0000)
#define BITMAP_MAIN_ADDR (BITMAP_GAS_ADDR + 20 * 1024 * 4)
#define OFFSET_DATA (0x0000 * 2)
struct device_data_s device_data __attribute__((section(".bss_ccm")));
const uint8_t * const modbus_map_ro[] = {
[OFFSET_DATA + 0] = (uint8_t *)&(device_data.peak[0]) + 1,
[OFFSET_DATA + 1] = (uint8_t *)&(device_data.peak[0]) + 0,
[OFFSET_DATA + 2] = (uint8_t *)&(device_data.peak[1]) + 1,
[OFFSET_DATA + 3] = (uint8_t *)&(device_data.peak[1]) + 0,
[OFFSET_DATA + 4] = (uint8_t *)&(device_data.peak[2]) + 1,
[OFFSET_DATA + 5] = (uint8_t *)&(device_data.peak[2]) + 0,
[OFFSET_DATA + 6] = (uint8_t *)&(device_data.peak[3]) + 1,
[OFFSET_DATA + 7] = (uint8_t *)&(device_data.peak[3]) + 0,
[OFFSET_DATA + 8] = (uint8_t *)&(device_data.freq[0]) + 1,
[OFFSET_DATA + 9] = (uint8_t *)&(device_data.freq[0]) + 0,
[OFFSET_DATA + 10] = (uint8_t *)&(device_data.freq[1]) + 1,
[OFFSET_DATA + 11] = (uint8_t *)&(device_data.freq[1]) + 0,
[OFFSET_DATA + 12] = (uint8_t *)&(device_data.freq[2]) + 1,
[OFFSET_DATA + 13] = (uint8_t *)&(device_data.freq[2]) + 0,
[OFFSET_DATA + 14] = (uint8_t *)&(device_data.freq[3]) + 1,
[OFFSET_DATA + 15] = (uint8_t *)&(device_data.freq[3]) + 0,
[OFFSET_DATA + 16] = (uint8_t *)&(device_data.button) + 0,
[OFFSET_DATA + 17] = (uint8_t *)&(device_data.sd) + 0,
};

25
ate/src/device.h Executable file
View File

@ -0,0 +1,25 @@
#ifndef __DEVICE_H__
#define __DEVICE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
/******************* device data *******************/
struct device_data_s {
uint16_t peak[4];
uint16_t freq[4];
uint8_t button;
uint8_t sd;
};
extern const uint8_t * const modbus_map_ro[];
extern struct device_data_s device_data;
#ifdef __cplusplus
}
#endif
#endif /* __DEVICE_H__ */

45
ate/src/heat.c Executable file
View File

@ -0,0 +1,45 @@
#include "heat.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
void heat_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = PIN_HEAT,
.GPIO_Mode = GPIO_Mode_OUT,
.GPIO_OType = GPIO_OType_PP,
.GPIO_Speed = GPIO_Speed_2MHz,
.GPIO_PuPd = GPIO_PuPd_NOPULL,
};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_Init(PORT_HEAT, &GPIO_InitStructure);
heat_off();
}
void heat_on(void)
{
GPIO_SetBits(PORT_HEAT, PIN_HEAT);
}
void heat_off(void)
{
GPIO_ResetBits(PORT_HEAT, PIN_HEAT);
}
void heat_toggle(void)
{
GPIO_ToggleBits(PORT_HEAT, PIN_HEAT);
}
void heat_loop(void)
{
static uint32_t ms = 0;
if (system_tick_cnt < (ms + 62)) {
return;
}
ms = system_tick_cnt;
heat_toggle();
}

25
ate/src/heat.h Executable file
View File

@ -0,0 +1,25 @@
#ifndef __HEAT_H__
#define __HEAT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define PORT_HEAT (GPIOB)
#define PIN_HEAT (GPIO_Pin_1)
extern uint32_t system_tick_cnt;
void heat_init(void);
void heat_on(void);
void heat_off(void);
void heat_toggle(void);
void heat_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __HEAT_H__ */

48
ate/src/led.c Executable file
View File

@ -0,0 +1,48 @@
#include "led.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
void led_init(uint16_t led)
{
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = led,
.GPIO_Mode = GPIO_Mode_OUT,
.GPIO_OType = GPIO_OType_PP,
.GPIO_Speed = GPIO_Speed_2MHz,
.GPIO_PuPd = GPIO_PuPd_NOPULL,
};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_Init(PORT_LED, &GPIO_InitStructure);
led_off(led);
}
void led_off(uint16_t led)
{
GPIO_SetBits(PORT_LED, led);
}
void led_on(uint16_t led)
{
GPIO_ResetBits(PORT_LED, led);
}
void led_loop(void)
{
static uint32_t ms = 0;
static uint32_t led_cnt = 0;
if (system_tick_cnt < (ms + 200)) {
return;
}
ms = system_tick_cnt;
led_cnt = led_cnt & 3;
switch (led_cnt) {
case 0: led_off(LED1 | LED2); break;
case 1: led_off(LED1); led_on(LED2);break;
case 2: led_on(LED1); led_off(LED2); break;
case 3: led_on(LED1 | LED2); break;
}
led_cnt++;
}

25
ate/src/led.h Executable file
View File

@ -0,0 +1,25 @@
#ifndef __LED_H__
#define __LED_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define PORT_LED (GPIOC)
#define LED1 (GPIO_Pin_4)
#define LED2 (GPIO_Pin_5)
extern uint32_t system_tick_cnt;
void led_init(uint16_t led);
void led_off(uint16_t led);
void led_on(uint16_t led);
void led_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __LED_H__ */

195
ate/src/ltc1867.c Executable file
View File

@ -0,0 +1,195 @@
#include "ltc1867.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_spi.h"
uint16_t data_ltc1867_raw[LTC1867_CH_CNT][LTC1867_RAW_BUFF_SIZE] __attribute__((section(".bss_ccm")));
struct data_ltc1867_s data_ltc1867 __attribute__((section(".bss_ccm")));
__attribute__((section(".data_ccm"))) uint16_t ltc1867_spi_data[LTC1867_CH_CNT] = {0xC400, 0x9400, 0xD400, 0x8400}; /* order: ch1, ch2, ch3, ch0 */
void ltc1867_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
SPI_InitTypeDef SPI_InitStructure;
/* TIM2 32bit for sample */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// NVIC_SetPriority(PendSV_IRQn, 1); /* priority is just lower than sample, for write cali data to flash */
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = TIMER_PERIOD_SAMPLE;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM2, 0, TIM_PSCReloadMode_Immediate);
/* TIM2 Interrupts enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
/* TIM3 16bit for ADC conversion */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = TIMER_PERIOD_DELAY;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM3, 0, TIM_PSCReloadMode_Immediate);
/* TIM3 disable counter, start when ltc1867 need delay */
TIM_Cmd(TIM3, DISABLE);
/* LEDIR pin configure */
GPIO_InitStructure.GPIO_Pin = PIN_LEDIR;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_Init(PORT_LEDIR, &GPIO_InitStructure);
ltc1867_ledir_off();
/* LTC1867 conv pin configure */
GPIO_InitStructure.GPIO_Pin = PIN_CONV;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_Init(PORT_LTC1867, &GPIO_InitStructure);
/* config SPI for LTC1867 communication */
GPIO_PinAFConfig(PORT_SPI, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(PORT_SPI, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(PORT_SPI, GPIO_PinSource7, GPIO_AF_SPI1);
GPIO_InitStructure.GPIO_Pin = PIN_SPI_SCK | PIN_SPI_SDI | PIN_SPI_SDO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(PORT_SPI, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
SPI_I2S_DeInit(SPI1);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
ltc1867_spi_select();
ltc1867_transfer(ltc1867_spi_data[LTC1867_CH_CNT - 1]);
data_ltc1867.ledir_cnt = 0; /* index of led count, for togglr IR led */
data_ltc1867.sample_cnt = 0; /* index for search point of 32768 */
for (uint8_t i = 0; i < LTC1867_CH_CNT; i++) {
data_ltc1867.sample_pre[i] = 0;
data_ltc1867.sample_now[i] = 0;
}
}
void ltc1867_ledir_on(void)
{
GPIO_SetBits(PORT_LEDIR, PIN_LEDIR);
}
void ltc1867_ledir_off(void)
{
GPIO_ResetBits(PORT_LEDIR, PIN_LEDIR);
}
void ltc1867_ledir_toggle(void)
{
GPIO_ToggleBits(PORT_LEDIR, PIN_LEDIR);
}
void ltc1867_delay(void)
{
FlagStatus sts;
TIM_SetCounter(TIM3, 0);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_Cmd(TIM3, ENABLE);
while (1) {
sts = TIM_GetFlagStatus(TIM3, TIM_FLAG_Update);
if (sts != RESET) {
break;
}
}
TIM_Cmd(TIM3, DISABLE);
}
void ltc1867_conv(void)
{
GPIO_SetBits(PORT_LTC1867, PIN_CONV);
}
void ltc1867_spi_select(void)
{
GPIO_ResetBits(PORT_LTC1867, PIN_SPI_CS);
}
uint16_t ltc1867_transfer(uint16_t data_send)
{
FlagStatus flag;
while (1) {
flag = SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE);
if (flag != RESET) {
break;
}
}
SPI_I2S_SendData(SPI1, data_send);
while (1) {
flag = SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);
if (flag != RESET) {
break;
}
}
return SPI_I2S_ReceiveData(SPI1);
}
void TIM2_IRQHandler(void)
{
static uint16_t pre_val[LTC1867_CH_CNT];
static uint16_t val[LTC1867_CH_CNT] = {65535, 65535, 65535, 65535};
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
/* for control led IR */
data_ltc1867.ledir_cnt++;
if (data_ltc1867.ledir_cnt == (SAMPLES_PER_PERIOD / 2)) {
ltc1867_ledir_on();
} else if (data_ltc1867.ledir_cnt >= SAMPLES_PER_PERIOD) {
ltc1867_ledir_off();
data_ltc1867.ledir_cnt = 0;
}
/* sample 4 channel adc data */
for (uint8_t i = 0; i < LTC1867_CH_CNT; i++) {
ltc1867_conv(); /* this point start convert */
ltc1867_delay(); /* delay 3.5us for convert time, reference for LTC1867 datasheet */
ltc1867_spi_select(); /* convert complete, make convert pin low for reading sample data by SPI */
pre_val[i] = val[i];
val[i] = ltc1867_transfer(ltc1867_spi_data[i]); /* read convert data and send next channel information */
data_ltc1867_raw[i][data_ltc1867.sample_cnt % LTC1867_RAW_BUFF_SIZE] = val[i];
if (pre_val[i] < 32768 && val[i] >= 32768) {
data_ltc1867.sample_pre[i] = data_ltc1867.sample_now[i];
data_ltc1867.sample_now[i] = data_ltc1867.sample_cnt;
}
}
data_ltc1867.sample_cnt++;
}

52
ate/src/ltc1867.h Executable file
View File

@ -0,0 +1,52 @@
#ifndef __LTC1867_H__
#define __LTC1867_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#include "config.h"
#define TIMER_SRC_FREQ (84 * 1000 * 1000)
#define TIMER_PERIOD_SAMPLE (TIMER_SRC_FREQ / LEDIR_FREQ / SAMPLES_PER_PERIOD - 1)
#define TIMER_PERIOD_DELAY (TIMER_SRC_FREQ / 1000 / 1000 * 35 / 10 - 1) /* 3.5us */
#define LTC1867_CH_CNT (4)
#define LTC1867_RAW_BUFF_SIZE (SAMPLES_PER_PERIOD * LEDIR_FREQ)
#define PORT_LEDIR (GPIOB)
#define PIN_LEDIR (GPIO_Pin_0)
#define PORT_LTC1867 (GPIOA)
#define PIN_CONV (GPIO_Pin_4)
#define PORT_SPI (GPIOA)
#define PIN_SPI_CS (GPIO_Pin_4)
#define PIN_SPI_SCK (GPIO_Pin_5)
#define PIN_SPI_SDO (GPIO_Pin_6)
#define PIN_SPI_SDI (GPIO_Pin_7)
struct data_ltc1867_s {
uint16_t ledir_cnt; /* index of led count, for togglr IR led */
uint32_t sample_cnt; /* index of sample */
uint32_t sample_pre[4]; /* index of pre sample rasing edge */
uint32_t sample_now[4]; /* index of now sample rasing edge */
};
extern struct data_ltc1867_s data_ltc1867;
extern uint16_t data_ltc1867_raw[LTC1867_CH_CNT][LTC1867_RAW_BUFF_SIZE];
void ltc1867_init(void);
void ltc1867_ledir_on(void);
void ltc1867_ledir_off(void);
void ltc1867_ledir_toggle(void);
void ltc1867_delay(void);
void ltc1867_conv(void);
void ltc1867_spi_select(void);
uint16_t ltc1867_transfer(uint16_t data_send);
#ifdef __cplusplus
}
#endif
#endif /* __LTC1867_H__ */

110
ate/src/ltc2640.c Executable file
View File

@ -0,0 +1,110 @@
#include "ltc2640.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_spi.h"
#include "stm32f4xx_dma.h"
#include "device.h"
uint8_t data_ltc2640_output[LTC2640_OUTPUT_LEN];
uint16_t data_ltc2640[] = {
VOLTAGE_200MV,
VOLTAGE_300MV,
VOLTAGE_400MV,
VOLTAGE_1000MV,
VOLTAGE_1200MV,
VOLTAGE_1500MV,
VOLTAGE_1800MV,
VOLTAGE_2000MV,
VOLTAGE_2400MV,
VOLTAGE_2500MV,
};
void ltc2640_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
/* config ltc2640 pin */
GPIO_InitStructure.GPIO_Pin = LTC2640_PIN_CS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LTC2640_PIN_SCK | LTC2640_PIN_SDI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);
/* config ltc2640 clr pin */
GPIO_InitStructure.GPIO_Pin = LTC2640_PIN_CLR;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, LTC2640_PIN_CLR);
/* config SPI function */
SPI_I2S_DeInit(SPI3);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI_InitStructure);
SPI_Cmd(SPI3, ENABLE);
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
/* Configure DMA controller to manage SPI request */
DMA_InitStructure.DMA_BufferSize = LTC2640_OUTPUT_LEN;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(SPI3->DR));
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)data_ltc2640_output;
DMA_Init(DMA1_Stream5, &DMA_InitStructure);
ltc2640_send_data(0);
}
void ltc2640_send_data(uint16_t data)
{
data_ltc2640_output[0] = 0x30;
data_ltc2640_output[1] = (uint8_t)((data >> 4) & 0xFF);
data_ltc2640_output[2] = (uint8_t)((data << 4) & 0xFF);
DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_TCIF5);
DMA_SetCurrDataCounter(DMA1_Stream5, LTC2640_OUTPUT_LEN);
DMA_Cmd(DMA1_Stream5, ENABLE);
}
void ltc2640_loop(void)
{
static uint32_t ms = 0;
static uint32_t cnt = 0;
if (system_tick_cnt < (ms + 100)) {
return;
}
GPIO_SetBits(GPIOA, LTC2640_PIN_CS);
ms = system_tick_cnt;
cnt = cnt % (sizeof(data_ltc2640) / sizeof(data_ltc2640[0]));
GPIO_ResetBits(GPIOA, LTC2640_PIN_CS);
ltc2640_send_data(data_ltc2640[cnt]);
cnt++;
}

38
ate/src/ltc2640.h Executable file
View File

@ -0,0 +1,38 @@
#ifndef __LTC2640_H__
#define __LTC2640_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define LTC2640_PIN_CLR (GPIO_Pin_7)
#define LTC2640_PIN_CS (GPIO_Pin_15)
#define LTC2640_PIN_SCK (GPIO_Pin_3)
#define LTC2640_PIN_SDI (GPIO_Pin_5)
#define LTC2640_OUTPUT_LEN (3)
#define VOLTAGE_200MV (328)
#define VOLTAGE_300MV (492)
#define VOLTAGE_400MV (655)
#define VOLTAGE_1000MV (1638)
#define VOLTAGE_1200MV (1966)
#define VOLTAGE_1500MV (2458)
#define VOLTAGE_1800MV (2949)
#define VOLTAGE_2000MV (3277)
#define VOLTAGE_2400MV (3932)
#define VOLTAGE_2500MV (4095)
extern uint32_t system_tick_cnt;
void ltc2640_init(void);
void ltc2640_send_data(uint16_t data);
void ltc2640_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __LTC2640_H__ */

185
ate/src/modbus.c Executable file
View File

@ -0,0 +1,185 @@
#include "device.h"
#include "rs485.h"
#include "modbus.h"
const uint8_t crc_tabl[] = { //CRC low Value Table
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40,
};
const uint8_t crc_tabh[] = { //CRC high Value Table
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40,
};
/* polynomial: x16+x15+x2+x1 */
void crc16_8005_calc(uint8_t * p, uint16_t len, struct crc16_result_s *ret)
{
struct crc16_result_s crc = {0xFF, 0xFF};
uint8_t i, index;
for (i = 0; i < len; i++) {
index = crc.crcl ^ p[i];
crc.crcl = crc.crch ^ crc_tabl[index];
crc.crch = crc_tabh[index];
}
ret->crcl = crc.crcl;
ret->crch = crc.crch;
}
void modbus_init(void)
{
rs485_init();
}
uint16_t modbus_data_big2little16(uint8_t *buff)
{
uint16_t val;
val = (uint16_t)(buff[0]);
val <<= 8;
val |= (uint16_t)(buff[1]);
return val;
}
uint32_t modbus_data_big2little32(uint8_t *buff)
{
uint32_t val;
val = (uint32_t)(buff[0]);
val <<= 8;
val |= (uint32_t)(buff[1]);
val <<= 8;
val |= (uint32_t)(buff[2]);
val <<= 8;
val |= (uint32_t)(buff[3]);
return val;
}
/* pr: point of rx buffer
pt: point of tx buffer
err_type: reference for MODBUS_ERROR_CODE_XXX
return: length of tx data need send */
uint16_t modbus_error_process(uint8_t *pr, uint8_t *pt, uint8_t err_type)
{
struct crc16_result_s crc;
pt[0] = pr[0];
pt[1] = pr[1] + 0x80;
pt[2] = err_type;
crc16_8005_calc(pt, 3, &crc);
pt[3] = crc.crcl;
pt[4] = crc.crch;
return 5;
}
/* pr: point of rx buffer
pt: point of tx buffer
len: length of rx data in buffer
return: length of tx data need send */
uint16_t modbus_func_read_input(uint8_t *pr, uint8_t *pt, uint16_t len)
{
uint16_t cnt, addr_s, i;
struct crc16_result_s crc;
/* modbus register count */
cnt = modbus_data_big2little16(pr + 4);
if (cnt != MODBUS_LENGTH_RO) {
/* modbus register count error */
return modbus_error_process(pr, pt, MODBUS_ERROR_CODE_VALUE);
}
addr_s = modbus_data_big2little16(pr + 2);
if (addr_s != MODBUS_ADDR_RO_S) {
/* modbus register address error */
return modbus_error_process(pr, pt, MODBUS_ERROR_CODE_ADDR);
}
pt[0] = pr[0];
pt[1] = pr[1];
pt[2] = (uint8_t)(cnt * 2);
for (i = 0; i < cnt * 2; i++) {
pt[3 + i] = *(modbus_map_ro[i]);
}
i += 3;
crc16_8005_calc(pt, i, &crc);
pt[i++] = crc.crcl;
pt[i++] = crc.crch;
return i;
}
void modbus_loop(void)
{
static uint32_t frame_cnt = 0;
struct crc16_result_s crc;
/* no new complete frame */
if (rs485_data.frame_cnt == frame_cnt) {
return;
}
/* one new frame occur */
frame_cnt = rs485_data.frame_cnt;
/* step 1: calc CRC */
crc16_8005_calc(rs485_data.buff_rx, rs485_data.rx_len - 2, &crc);
if (crc.crcl != rs485_data.buff_rx[rs485_data.rx_len - 2] || \
crc.crch != rs485_data.buff_rx[rs485_data.rx_len - 1]) {
/* CRC calc error */
rs485_data.rx_len = 0;
rs485_mode_rx();
rs485_rx_start();
return;
}
/* step 2: process data according function code */
if (rs485_data.buff_rx[1] == MODBUS_FUNCTION_CODE_READ_INPUT) {
rs485_data.tx_len = modbus_func_read_input(rs485_data.buff_rx, rs485_data.buff_tx, rs485_data.rx_len);
} else {
rs485_data.tx_len = modbus_error_process(rs485_data.buff_rx, rs485_data.buff_tx, MODBUS_ERROR_CODE_FUNCTION);
}
if (rs485_data.tx_len == 0) {
rs485_data.rx_len = 0;
rs485_mode_rx();
rs485_rx_start();
} else {
rs485_send_data(rs485_data.tx_len);
}
}

37
ate/src/modbus.h Executable file
View File

@ -0,0 +1,37 @@
#ifndef __MODBUS_H__
#define __MODBUS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define MODBUS_FUNCTION_CODE_READ_INPUT (0x04)
#define MODBUS_FUNCTION_CODE_WRITE_SINGLE (0x06)
#define MODBUS_FUNCTION_CODE_WRITE_MULTI (0x10)
#define MODBUS_ERROR_CODE_FUNCTION (0x01)
#define MODBUS_ERROR_CODE_ADDR (0x02)
#define MODBUS_ERROR_CODE_VALUE (0x03)
#define MODBUS_ERROR_CODE_EXECUTE (0x04)
#define MODBUS_ADDR_RO_S (0x1234)
#define MODBUS_LENGTH_RO (9)
struct crc16_result_s {
uint8_t crch;
uint8_t crcl;
};
void crc16_8005_calc(uint8_t * p, uint16_t len, struct crc16_result_s *ret);
void modbus_init(void);
uint16_t modbus_data_big2little16(uint8_t *buff);
uint32_t modbus_data_big2little32(uint8_t *buff);
void modbus_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __MODBUS_H__ */

208
ate/src/rs485.c Executable file
View File

@ -0,0 +1,208 @@
#include "rs485.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_dma.h"
struct rs485_data_s rs485_data;
uint8_t rs485_buff_tx[RS485_BUFF_TX_LEN] __attribute__((aligned(16)));
uint8_t rs485_buff_rx[RS485_BUFF_RX_LEN];
void rs485_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* init struct data */
rs485_data.baudrate = RS485_DEFAULT_BAUDRATE;
rs485_data.parity = RS485_DEFAULT_PARITY;
rs485_data.stopbits = RS485_DEFAULT_STOPBITS;
rs485_data.addr = 0x5A;
rs485_data.rx_len = 0;
rs485_data.tx_len = 0;
rs485_data.buff_rx = rs485_buff_rx;
rs485_data.buff_tx = rs485_buff_tx;
rs485_data.frame_cnt = 0;
/* config modbus direction pin */
GPIO_InitStructure.GPIO_Pin = RS485_PIN_DIR,
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT,
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP,
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz,
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL,
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_Init(RS485_PORT, &GPIO_InitStructure);
rs485_mode_rx();
/* config rs485 uart pin */
GPIO_PinAFConfig(RS485_PORT, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(RS485_PORT, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_InitStructure.GPIO_Pin = RS485_PIN_TX | RS485_PIN_RX;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(RS485_PORT, &GPIO_InitStructure);
/* config rs485 uart function */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
USART_DeInit(USART1);
USART_OverSampling8Cmd(USART1, ENABLE);
USART_InitStructure.USART_BaudRate = rs485_data.baudrate;
/* When using Parity the word length must be configured to 9 bits */
if (rs485_data.parity == RS485_PARITY_ODD) {
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Odd;
} else if (rs485_data.parity == RS485_PARITY_EVEN) {
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Even;
} else {
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No;
}
if (rs485_data.stopbits == 2) {
USART_InitStructure.USART_StopBits = USART_StopBits_2;
} else {
USART_InitStructure.USART_StopBits = USART_StopBits_1;
}
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
USART_Cmd(USART1, ENABLE);
/* Configure DMA controller to manage USART TX request */
DMA_InitStructure.DMA_BufferSize = RS485_BUFF_TX_LEN;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(USART1->DR));
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rs485_buff_tx;
DMA_Init(DMA2_Stream7, &DMA_InitStructure);
/* Configure interrupt for USART1 RX */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_TC, ENABLE);
/* config TIM4 for modbus recv timeout, 3.5 frame time */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
if (rs485_data.baudrate >= 19200) {
TIM_TimeBaseStructure.TIM_Period = 1750;
} else {
TIM_TimeBaseStructure.TIM_Period = 1000 * 1000 * 35 / rs485_data.baudrate;
}
TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM4, 84 - 1, TIM_PSCReloadMode_Immediate);
/* TIM4 disable counter, start after reciving every uart data */
TIM_Cmd(TIM4, DISABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void rs485_timer_restart(void)
{
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
TIM_SetCounter(TIM4, 0);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
void rs485_timer_stop(void)
{
TIM_Cmd(TIM4, DISABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
void rs485_mode_tx(void)
{
GPIO_SetBits(RS485_PORT, RS485_PIN_DIR);
}
void rs485_mode_rx(void)
{
GPIO_ResetBits(RS485_PORT, RS485_PIN_DIR);
}
void rs485_rx_start(void)
{
/* clear PE, FE, NE, ORE and IDLE flags, reference USART_ClearFlag function */
USART_GetITStatus(USART1, USART_IT_RXNE);
USART_ReceiveData(USART1);
USART_ClearFlag(USART1, USART_FLAG_RXNE);
/* enable USART receive interrupt */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
void rs485_rx_stop(void)
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
void rs485_send_data(uint16_t len)
{
rs485_mode_tx();
DMA_SetCurrDataCounter(DMA2_Stream7, len);
USART_ClearITPendingBit(USART1, USART_IT_TC);
DMA_Cmd(DMA2_Stream7, ENABLE);
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
rs485_timer_restart();
if (rs485_data.rx_len < RS485_BUFF_RX_LEN) {
rs485_buff_rx[rs485_data.rx_len++] = USART_ReceiveData(USART1);
} else {
/* exception, has recevered too much data, drop */
rs485_data.rx_len = 0;
}
}
/* one tx frame complete */
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) {
USART_ClearITPendingBit(USART1, USART_IT_TC);
DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
rs485_data.rx_len = 0;
rs485_mode_rx();
rs485_rx_start();
}
}
void TIM4_IRQHandler(void)
{
rs485_timer_stop();
if (rs485_data.buff_rx[0] == rs485_data.addr && rs485_data.rx_len > 3) {
/* one completed frame, need processing */
rs485_rx_stop();
rs485_data.frame_cnt++;
} else {
/* address not match, drop */
rs485_data.rx_len = 0;
}
}

53
ate/src/rs485.h Executable file
View File

@ -0,0 +1,53 @@
#ifndef __RS485_H__
#define __RS485_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define RS485_PORT (GPIOA)
#define RS485_PIN_DIR (GPIO_Pin_8)
#define RS485_PIN_TX (GPIO_Pin_9)
#define RS485_PIN_RX (GPIO_Pin_10)
#define RS485_PARITY_NONE (0)
#define RS485_PARITY_ODD (1)
#define RS485_PARITY_EVEN (2)
#define RS485_DEFAULT_BAUDRATE (19200)
#define RS485_DEFAULT_PARITY (RS485_PARITY_NONE)
#define RS485_DEFAULT_STOPBITS (1)
#define RS485_BUFF_TX_LEN (1024)
#define RS485_BUFF_RX_LEN (1024)
struct rs485_data_s {
uint32_t baudrate;
uint8_t parity;
uint8_t stopbits;
uint8_t addr;
uint16_t rx_len;
uint16_t tx_len;
uint8_t *buff_rx;
uint8_t *buff_tx;
uint32_t frame_cnt;
};
extern struct rs485_data_s rs485_data;
void rs485_init(void);
void rs485_timer_restart(void);
void rs485_timer_stop(void);
void rs485_mode_tx(void);
void rs485_mode_rx(void);
void rs485_rx_start(void);
void rs485_rx_stop(void);
void rs485_send_data(uint16_t len);
#ifdef __cplusplus
}
#endif
#endif /* __RS485_H__ */

76
ate/src/sd.c Executable file
View File

@ -0,0 +1,76 @@
#include "ff.h"
#include "sd.h"
#include "sdio_sd.h"
#include "device.h"
#define RETRY_MAX (3)
FATFS fs;
TCHAR file_name[FILE_NAME_LEN];
uint8_t sd_detect(void)
{
SD_Error sd_err;
FRESULT ret;
uint32_t retry;
DIR dir;
TCHAR name[FILE_NAME_LEN];
retry = RETRY_MAX;
while (retry--) {
sd_err = SD_Init();
if (sd_err == SD_OK) {
break;
} else if (retry == 0) {
SD_DeInit();
return SD_STS_ERR_INIT;
}
}
retry = RETRY_MAX;
while (retry--) {
ret = f_mount(0, &fs);
if (ret == FR_OK) {
break;
} else {
SD_DeInit();
return SD_STS_ERR_MOUNT;
}
}
retry = RETRY_MAX;
while (retry--) {
ret = f_getcwd(name, sizeof(name));
if (ret == FR_OK) {
break;
} else {
SD_DeInit();
return SD_STS_ERR_GETCWD;
}
}
retry = RETRY_MAX;
while (retry--) {
ret = f_opendir(&dir, name);
if (ret == FR_OK) {
break;
} else {
SD_DeInit();
return SD_STS_ERR_OPENDIR;
}
}
return SD_STS_OK;
}
void sd_loop(void)
{
static uint32_t ms = 0;
if (system_tick_cnt < (ms + 500)) {
return;
}
ms = system_tick_cnt;
device_data.sd = sd_detect();
}

29
ate/src/sd.h Executable file
View File

@ -0,0 +1,29 @@
#ifndef __SD_H__
#define __SD_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#include "ff.h"
#define SD_STS_NULL (0)
#define SD_STS_ERR_INIT (1)
#define SD_STS_ERR_MOUNT (2)
#define SD_STS_ERR_GETCWD (3)
#define SD_STS_ERR_OPENDIR (4)
#define SD_STS_OK (5)
#define FILE_NAME_LEN (13)
extern uint32_t system_tick_cnt;
uint8_t sd_detect(void);
void sd_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __SD_H__ */

370
ate/start.S Executable file
View File

@ -0,0 +1,370 @@
.syntax unified
.cpu cortex-m4
.thumb
.global g_pfnVectors
.global Default_Handler
.global Reset_Handler
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
cpsid i /* disable irq */
ldr r0, =_stack_top
msr msp, r0
/* load data section */
ldr r0, =_data_load
ldr r1, =_data_run
ldr r2, =_data_run_end
cmp r1, r2
bhs 2f
1:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
blo 1b
2:
/* clear bss section */
ldr r0, =0
ldr r1, =_bss_run
ldr r2, =_bss_run_end
cmp r1, r2
bhs 2f
1:
str r0, [r1], #4
cmp r1, r2
blo 1b
2:
/* load data_ccm section */
ldr r0, =_data_ccm_load
ldr r1, =_data_ccm_run
ldr r2, =_data_ccm_run_end
cmp r1, r2
bhs 2f
1:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
blo 1b
2:
/* clear bss_ccm section */
ldr r0, =0
ldr r1, =_bss_ccm_run
ldr r2, =_bss_ccm_run_end
cmp r1, r2
bhs 2f
1:
str r0, [r1], #4
cmp r1, r2
blo 1b
2:
bl SystemInit
bl main
b .
.size Reset_Handler, .-Reset_Handler
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
MRS r0, msp
STMFD r0!, {r4 - r11}
STMFD r0!, {lr}
MSR msp, r0
PUSH {lr}
BL coredump
POP {lr}
POP {lr}
POP {r4 - r11}
BX lr
.size Default_Handler, .-Default_Handler
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _stack_top
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_IRQHandler /* PVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FSMC_IRQHandler /* FSMC */
.word SDIO_IRQHandler /* SDIO */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word ETH_IRQHandler /* Ethernet */
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
.word CAN2_TX_IRQHandler /* CAN2 TX */
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
.word CRYP_IRQHandler /* CRYP crypto */
.word HASH_RNG_IRQHandler /* Hash and Rng */
.word FPU_IRQHandler /* FPU */
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
/* External Interrupts */
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler
.weak CAN1_RX0_IRQHandler
.thumb_set CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_TIM9_IRQHandler
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
.weak TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_TIM11_IRQHandler
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FSMC_IRQHandler
.thumb_set FSMC_IRQHandler,Default_Handler
.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak CAN2_TX_IRQHandler
.thumb_set CAN2_TX_IRQHandler,Default_Handler
.weak CAN2_RX0_IRQHandler
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
.weak CAN2_RX1_IRQHandler
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak DCMI_IRQHandler
.thumb_set DCMI_IRQHandler,Default_Handler
.weak CRYP_IRQHandler
.thumb_set CRYP_IRQHandler,Default_Handler
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler