调通串口与上位机双向通信

- UART2 TX: 硬件FIFO+DMA+块传输模式,非阻塞发送
- UART2 RX: 硬件FIFO+中断+软件FIFO,状态机解析协议帧
- 协议: [SOF:0xA7][cmd:1][checksum:1],支持自动/手动/调试模式切换
- 更新.gitignore忽略*.log文件
This commit is contained in:
2026-06-07 11:42:15 +08:00
committed by SkyLi
parent f28d129e11
commit d120fa0d17
4 changed files with 165 additions and 86 deletions
+1
View File
@@ -6,5 +6,6 @@
uv4.log uv4.log
uv4.log.lock uv4.log.lock
keil-assistant.log keil-assistant.log
*.log
CLAUDE.md CLAUDE.md
+75 -3
View File
@@ -2,7 +2,9 @@
#include "zf_driver_uart.h" #include "zf_driver_uart.h"
#include "zf_common_interrupt.h" #include "zf_common_interrupt.h"
#include "ti/driverlib/dl_uart_main.h" #include "ti/driverlib/dl_uart_main.h"
#include "ti/driverlib/dl_dma.h"
#include "zf_common_fifo.h" #include "zf_common_fifo.h"
#include "Beep.h"
volatile fifo_struct command_fifo = {0}; volatile fifo_struct command_fifo = {0};
volatile uint8_t command_fifo_buffer[COMMAND_FIFO_BUFFER_SIZE] = {0}; volatile uint8_t command_fifo_buffer[COMMAND_FIFO_BUFFER_SIZE] = {0};
@@ -19,13 +21,27 @@ void command_init()
{ {
uart_init(UART_2,115200,UART2_TX_B15,UART2_RX_B16); uart_init(UART_2,115200,UART2_TX_B15,UART2_RX_B16);
uart_set_interrupt_config(UART_2,UART_INTERRUPT_CONFIG_RX_ENABLE); uart_set_interrupt_config(UART_2,UART_INTERRUPT_CONFIG_RX_ENABLE);
interrupt_set_priority(UART2_INT_IRQn,1);//设置为与主要任务平行的优先级 interrupt_set_priority(UART2_INT_IRQn,2);//设置为次于主要任务的优先级
//开启发送DMA //开启发送DMA
static const DL_DMA_Config dma_tx_config =
{
.trigger = DMA_UART2_TX_TRIG,
.triggerType = DL_DMA_TRIGGER_TYPE_EXTERNAL,
.transferMode = DL_DMA_SINGLE_TRANSFER_MODE,
.extendedMode = DL_DMA_NORMAL_MODE,
.srcWidth = DL_DMA_WIDTH_BYTE,
.destWidth = DL_DMA_WIDTH_BYTE,
.srcIncrement = DL_DMA_ADDR_INCREMENT,
.destIncrement = DL_DMA_ADDR_UNCHANGED,
};
DL_DMA_initChannel(DMA, 0, &dma_tx_config);
DL_UART_Main_enableDMATransmitEvent(UART2);
//开启硬件FIFO //开启硬件FIFO
DL_UART_Main_enableFIFOs(UART2); DL_UART_Main_enableFIFOs(UART2);
DL_UART_Main_setRXFIFOThreshold(UART2,DL_UART_MAIN_RX_FIFO_LEVEL_1_2_FULL); DL_UART_Main_setRXFIFOThreshold(UART2,DL_UART_MAIN_RX_FIFO_LEVEL_ONE_ENTRY);
DL_UART_Main_setTXFIFOThreshold(UART2,DL_UART_MAIN_TX_FIFO_LEVEL_ONE_ENTRY);
//设置软件FIFO //设置软件FIFO
fifo_init((fifo_struct *)&command_fifo,FIFO_DATA_8BIT,(void*)command_fifo_buffer,COMMAND_FIFO_BUFFER_SIZE); fifo_init((fifo_struct *)&command_fifo,FIFO_DATA_8BIT,(void*)command_fifo_buffer,COMMAND_FIFO_BUFFER_SIZE);
@@ -35,7 +51,55 @@ void command_init()
//从软件FIFO中解析数据包并执行 //从软件FIFO中解析数据包并执行
void command_task() void command_task()
{ {
static uint8_t state = 0;
static uint8_t cmd;
uint8_t byte;
while(fifo_used((fifo_struct*)&command_fifo) > 0)
{
switch(state)
{
case 0: // 等待SOF 0xA7
fifo_read_element((fifo_struct*)&command_fifo, &byte, FIFO_READ_AND_CLEAN);
if(byte == 0xA7) state = 1;
break;
case 1: // 读取cmd
fifo_read_element((fifo_struct*)&command_fifo, &cmd, FIFO_READ_AND_CLEAN);
state = 2;
break;
case 2: // 校验checksum = SOF + cmd
fifo_read_element((fifo_struct*)&command_fifo, &byte, FIFO_READ_AND_CLEAN);
if(byte == (uint8_t)(0xA7 + cmd))
{
switch(cmd)
{
case 0x01: SwitchToAutoMode(); break;
case 0x02: SwitchToManualMode(); break;
case 0x03: SwitchToDebugMode(); break;
}
}
state = 0;
break;
}
}
}
//切换到自动模式
void SwitchToAutoMode()
{
beep_on_time(100);
}
//切换到手动模式
void SwitchToManualMode()
{
beep_on_time(200);
}
//切换到调试模式
void SwitchToDebugMode()
{
beep_on_time(300);
} }
//DMA发送使用的地址 //DMA发送使用的地址
uint8_t angle_velocity_data[6] = {0}; uint8_t angle_velocity_data[6] = {0};
@@ -43,16 +107,24 @@ uint8_t angle_velocity_data[6] = {0};
void command_send_angle_velocity(float* pointer_angle_velocity) void command_send_angle_velocity(float* pointer_angle_velocity)
{ {
//等待上一次DMA发送完成 //等待上一次DMA发送完成
while(DL_DMA_isChannelEnabled(DMA, 0));
//等待UART物理发送完成
while(!DL_UART_isTXFIFOEmpty(UART2));
//填充数据 //填充数据
uint8_t* p = (uint8_t*)pointer_angle_velocity; uint8_t* p = (uint8_t*)pointer_angle_velocity;
angle_velocity_data[0]=0xA1; angle_velocity_data[0]=0xA9;
angle_velocity_data[1]=*(p++); angle_velocity_data[1]=*(p++);
angle_velocity_data[2]=*(p++); angle_velocity_data[2]=*(p++);
angle_velocity_data[3]=*(p++); angle_velocity_data[3]=*(p++);
angle_velocity_data[4]=*(p++); angle_velocity_data[4]=*(p++);
angle_velocity_data[5]=command_sum(angle_velocity_data,5); angle_velocity_data[5]=command_sum(angle_velocity_data,5);
//DMA发送(非阻塞) //DMA发送(非阻塞)
DL_DMA_setSrcAddr(DMA, 0, (uint32_t)angle_velocity_data);
DL_DMA_setDestAddr(DMA, 0, (uint32_t)&UART2->TXDATA);
DL_DMA_setTransferSize(DMA, 0, 6);
DL_DMA_enableChannel(DMA, 0);
// UART TX FIFO为空,DMA触发条件已满足,使能通道即自动开始传输
} }
uint8_t command_sum(uint8_t* data,int len) uint8_t command_sum(uint8_t* data,int len)
+4
View File
@@ -9,4 +9,8 @@ void command_init();
void command_task(); void command_task();
void command_send_angle_velocity(float* pointer_angle_velocity); void command_send_angle_velocity(float* pointer_angle_velocity);
void SwitchToAutoMode();
void SwitchToManualMode();
void SwitchToDebugMode();
#endif #endif
+3 -1
View File
@@ -46,6 +46,7 @@
#include "Beep.h" #include "Beep.h"
#include "GrayscaleSensor.h" #include "GrayscaleSensor.h"
#include "MotorEncoder.h" #include "MotorEncoder.h"
#include "Command.h"
/* /*
定时器资源分配: 定时器资源分配:
@@ -60,7 +61,7 @@ G6 20Hz任务
0 GPIOA_INT_IRQn 外部中断模拟四倍频正交编码器 0 GPIOA_INT_IRQn 外部中断模拟四倍频正交编码器
1 TIMA0_INT_IRQn 100Hz任务 1 TIMA0_INT_IRQn 100Hz任务
1 TIMA1_INT_IRQn 50Hz任务 1 TIMA1_INT_IRQn 50Hz任务
1 UART2_INT_IRQn Command串口接收中断 2 UART2_INT_IRQn Command串口接收中断
7 TIMG6_INT_IRQn 20Hz任务 7 TIMG6_INT_IRQn 20Hz任务
*/ */
int main (void) int main (void)
@@ -75,6 +76,7 @@ int main (void)
imu_calibrate_gyro(); // IMU 陀螺仪零偏校准 需要在静止状态下调用 imu_calibrate_gyro(); // IMU 陀螺仪零偏校准 需要在静止状态下调用
grayscale_sensor_init();//灰度传感器初始化 grayscale_sensor_init();//灰度传感器初始化
motor_encoder_init();//电机编码器初始化 motor_encoder_init();//电机编码器初始化
command_init();
task_init(); task_init();