AT32F413工程 DMA IDLE

### 一份简单的AT32工程的IDLE代码

#### 在本人的环境下编译没有问题

/**

 *  全局变量区域

 * **/

#if USART_DMA

uint8_t usart1_dma_send[USART_DMA_DATA_LEN];

uint8_t usart1_dma_recv[USART_DMA_DATA_LEN];

uint8_t usart3_dma_send[USART_DMA_DATA_LEN];

uint8_t usart3_dma_recv[USART_DMA_DATA_LEN];

#endif

/**

 * @brief

 * @note    PA9: Tx

 *          PA10: Rx

 * @return ** void

 */

static void USART1_GPIO_Init(void)

{

    gpio_init_type gpio_init_struct;

    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;

    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;

    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;

    gpio_init_struct.gpio_pins = GPIO_PINS_9;

    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;

    gpio_init(GPIOA, &gpio_init_struct);

    gpio_init_struct.gpio_pins = GPIO_PINS_10;

    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;

    gpio_init_struct.gpio_pull = GPIO_PULL_UP;

    gpio_init(GPIOA, &gpio_init_struct);

}

/**

 * @brief

 * @note    PB10: Tx

 *          PB11: Rx

 * @return ** void

 */

static void USART3_GPIO_Init(void)

{

    gpio_init_type gpio_init_struct;

 

    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;

    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;

    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;

    gpio_init_struct.gpio_pins = GPIO_PINS_10;

    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;

    gpio_init(GPIOB, &gpio_init_struct);

    gpio_init_struct.gpio_pins = GPIO_PINS_11;

    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;

    gpio_init_struct.gpio_pull = GPIO_PULL_UP;

    gpio_init(GPIOB, &gpio_init_struct);

}

void usart1_init(void)

{

    USART1_GPIO_Init();

   

    crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);

   

//    usart_init(USART1,CH343_BAUDRATE,USART_DATA_8BITS,USART_STOP_1_BIT);      //波特率1M,8位数据位,1位停止位,无校验

    // usart_parity_selection_config(USART1, USART_PARITY_EVEN);

    usart_init(USART1,115200,USART_DATA_8BITS,USART_STOP_1_BIT);      //波特率1M,8位数据位,1位停止位,无校验

   

    usart_transmitter_enable(USART1, TRUE);

    usart_receiver_enable(USART1, TRUE);

   

    usart_dma_transmitter_enable(USART1, TRUE);

    usart_dma_receiver_enable(USART1, TRUE);

    // usart_hardware_flow_control_set(USART1, USART_HARDWARE_FLOW_NONE);       // 硬件流控制

    usart_interrupt_enable(USART1,USART_IDLE_INT,TRUE);

    nvic_irq_enable(USART1_IRQn, 0, 0);     // 开启这个才实际使能了中断

    usart_enable(USART1, TRUE);

}

void usart3_init(void)

{

    USART3_GPIO_Init();

   

    crm_periph_clock_enable(CRM_USART3_PERIPH_CLOCK, TRUE);

    usart_parity_selection_config(USART3, USART_PARITY_EVEN);

    usart_init(USART3,115200,USART_DATA_9BITS,USART_STOP_1_BIT);      //波特率1M,8位数据位,1位停止位,无校验

    // usart_init(USART3,CH343_BAUDRATE,USART_DATA_8BITS,USART_STOP_1_BIT);

   

    usart_transmitter_enable(USART3, TRUE);

    usart_receiver_enable(USART3, TRUE);

   usart_dma_transmitter_enable(USART3, TRUE);

    usart_dma_receiver_enable(USART3, TRUE);

    // usart_hardware_flow_control_set(USART3, USART_HARDWARE_FLOW_NONE);       // 硬件流控

    // 开启空闲中断和错误中断

    // usart_interrupt_enable(USART3,USART_IDLE_INT|USART_ERR_INT,TRUE);

    usart_interrupt_enable(USART3,USART_IDLE_INT,TRUE);

    nvic_irq_enable(USART3_IRQn, 0, 0);     // 开启这个才实际使能了中断

    usart_enable(USART3, TRUE);

}

/**

  * @brief  init dma1 channel1 for "usart1_rx"

  * @param  none

  * @retval none

  */

void usart_dma1_channel1_init(void)

{

    dma_init_type dma_init_struct;

    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

    dma_reset(DMA1_CHANNEL1);

    dma_default_para_init(&dma_init_struct);

    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;

    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;

    dma_init_struct.memory_inc_enable = TRUE;

    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

    dma_init_struct.peripheral_inc_enable = FALSE;

    dma_init_struct.priority = DMA_PRIORITY_LOW;

    dma_init_struct.loop_mode_enable = FALSE;

    // dma_init_struct.loop_mode_enable = TRUE;

    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    /* flexible function enable */

    dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_RX);

}

/**

  * @brief  init dma1 channel2 for "usart1_tx"

  * @param  none

  * @retval none

  */

void usart_dma1_channel2_init(void)

{

    dma_init_type dma_init_struct;

    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

    dma_reset(DMA1_CHANNEL2);

    dma_default_para_init(&dma_init_struct);

    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;

    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;

    dma_init_struct.memory_inc_enable = TRUE;

    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

    dma_init_struct.peripheral_inc_enable = FALSE;

    dma_init_struct.priority = DMA_PRIORITY_LOW;

    dma_init_struct.loop_mode_enable = FALSE;

    // dma_init_struct.loop_mode_enable = TRUE;

    dma_init(DMA1_CHANNEL2, &dma_init_struct);

    dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);

    nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);

    dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART1_TX);

}

/**

  * @brief  init dma2 channel1 for "usart3_rx"

  * @param  none

  * @retval none

  */

void usart_dma2_channel1_init(void)

{

    dma_init_type dma_init_struct;

    crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);

    dma_reset(DMA2_CHANNEL1);

    dma_default_para_init(&dma_init_struct);

    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;

    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;

    dma_init_struct.memory_inc_enable = TRUE;

    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

    dma_init_struct.peripheral_inc_enable = FALSE;

    dma_init_struct.priority = DMA_PRIORITY_LOW;

    dma_init_struct.loop_mode_enable = FALSE;

    // dma_init_struct.loop_mode_enable = TRUE;

    dma_init(DMA2_CHANNEL1, &dma_init_struct);

    dma_flexible_config(DMA2, FLEX_CHANNEL1, DMA_FLEXIBLE_UART3_RX);

}

/**

  * @brief  init dma2 channel2 for "usart3_tx"

  * @param  none

  * @retval none

  */

void usart_dma2_channel2_init(void)

{

    dma_init_type dma_init_struct;

    crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);

    dma_reset(DMA2_CHANNEL2);

    dma_default_para_init(&dma_init_struct);

    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;

    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;

    dma_init_struct.memory_inc_enable = TRUE;

    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

    dma_init_struct.peripheral_inc_enable = FALSE;

    dma_init_struct.priority = DMA_PRIORITY_LOW;

    dma_init_struct.loop_mode_enable = FALSE;

    dma_init(DMA2_CHANNEL2, &dma_init_struct);

    dma_interrupt_enable(DMA2_CHANNEL2, DMA_FDT_INT, TRUE);

    nvic_irq_enable(DMA2_Channel2_IRQn, 0, 0);

    dma_flexible_config(DMA2, FLEX_CHANNEL2, DMA_FLEXIBLE_UART3_TX);    

}

/**

  * @brief  config dma channel transfer parameter

  * @param  none

  * @retval none

  */

void usart_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size)

{

    dmax_channely->dtcnt = buffer_size;

    dmax_channely->paddr = peripheral_base_addr;

    dmax_channely->maddr = memory_base_addr;

}

void USART_Config(void)

{  

    // usart1 接收

    usart_dma1_channel1_init();

    usart_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, usart1_dma_recv, USART_DMA_DATA_LEN);

    dma_channel_enable(DMA1_CHANNEL1, TRUE);

   

    // usart1 send

    usart_dma1_channel2_init();

    usart_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, usart1_dma_send, USART_DMA_DATA_LEN);

    dma_channel_enable(DMA1_CHANNEL2, FALSE);

    // usart3 recv

    usart_dma2_channel1_init();

    usart_dma_channel_config(DMA2_CHANNEL1, (uint32_t)&USART3->dt, usart3_dma_recv, USART_DMA_DATA_LEN);

    dma_channel_enable(DMA2_CHANNEL1, TRUE);

    // usart3 send

    usart_dma2_channel2_init();

    usart_dma_channel_config(DMA2_CHANNEL2, (uint32_t)&USART3->dt, usart3_dma_send, USART_DMA_DATA_LEN);

    dma_channel_enable(DMA2_CHANNEL2, FALSE);       // 关闭传输

       

    // 串口初始化

    usart1_init();

    usart3_init();

}

void DMA2_Channel2_IRQHandler(void)

{

    if(dma_interrupt_flag_get(DMA2_FDT2_FLAG))

    {

        dma_channel_enable(DMA2_CHANNEL2, FALSE);

        dma_flag_clear(DMA2_FDT2_FLAG);        

    }

}

void USART3_IRQHandler(void)

{

    // 处理时间大概40us左右

    if((0xAA == usart3_dma_recv[0])

    &&(0xBB == usart3_dma_recv[usart3_dma_recv[1]])

    ){

        in_queue(&recv_usart_fifo_ctrl,(uint8_t* )usart3_dma_recv);

    }

   

    usart_flag_clear (USART3, USART_IDLEF_FLAG);

    usart13_dma_recv_clear(USART3);

    // delay_ms(2);

    usart13_dma_send_data(USART3,usart3_dma_recv,10);

}

<think>好的,我现在需要帮助用户完成基于STM32的足底按摩机器人硬件和软件设计。首先,我得回顾之前的对话,用户之前已经介绍了项目的大致框架,包括中医手法调研、数学建模和机构设计。现在他们具体询问的是硬件和软件的实现,特别是STM32和Keil MDK的应用。 首先,我需要确定用户的需求是什么。他们可能是一个工程团队或者学生,正在开发一个足底按摩机器人,需要具体的硬件电路设计和软件程序开发指导。用户可能已经完成了理论部分,现在进入实施阶段,需要具体的实现方案。 接下来,分析用户的问题。硬件部分包括STM32微控制器的选型,各个模块的电路设计,比如电源、电机驱动、传感器、通信模块等。软件部分包括主程序、靶点定位、力度控制、手法程序等。用户可能希望得到一个结构化的设计指南,包含各个模块的具体实现方法和注意事项。 需要考虑用户可能没有明确提到的深层需求。例如,系统的实时性、稳定性、安全性,以及如何将之前的数学建模(如运动学模型、接触力学模型)整合到软件控制中。此外,硬件设计中的EMC问题、电源管理,软件中的多任务调度、中断处理等也是需要考虑的。 然后,我需要组织回答的结构。按照硬件设计和软件设计两大部分来展开。硬件部分需要涵盖各个子模块的设计要点,软件部分则需要说明各个功能模块的实现方法。同时,要结合之前的数学建模,比如PID控制、路径规划算法等,确保软硬件的协同工作。 在硬件设计中,STM32的选型是关键,需要考虑IO数量、ADC/DAC需求、通信接口等。电源模块需要稳定,可能涉及降压和稳压电路。电机驱动部分要根据电机类型选择合适的驱动芯片,比如直流电机常用H桥,步进电机可能需要专用驱动器。传感器部分需要处理模拟信号,可能用到滤波电路和信号调理。通信模块可能需要CAN或蓝牙,确保数据传输的可靠性。 软件设计方面,主程序需要初始化外设,管理任务调度。靶点定位可能涉及坐标转换算法,将反射区的位置转换为机械臂的运动坐标。按摩力度控制需要结合PID算法和压力传感器的反馈,实现闭环控制。手法程序设计则需要将不同的按摩手法转化为具体的运动轨迹和力度变化,可能需要状态机来实现不同手法的切换。 还要考虑安全机制,比如紧急停止、力度过载保护,这些需要在硬件和软件中都有相应的措施。例如,硬件上的急停按钮,软件中的看门狗和异常检测。 最后,需要验证整个系统的可行性,建议用户进行模块化测试,分步验证每个功能,再进行集成测试。同时,注意文档的编写和后续的维护升级可能。 总结,用户需要一个全面而详细的实现方案,涵盖硬件电路和软件程序的设计要点,确保系统稳定可靠,并且能够实现之前设定的各种按摩功能和效果。</think>以下为基于STM32的足底按摩机器人硬件与软件系统设计方案,采用模块化开发思路: --- ### **一、硬件系统设计** #### 1. 核心控制模块 ```c // STM32F407ZET6最小系统 [主芯片] STM32F407ZET6(168MHz, 1MB Flash, 192KB RAM) [时钟电路] 8MHz晶振+32.768kHz RTC [供电电路] LM2596降压至3.3V(输入12V/2A) [调试接口] SWD四线调试接口 ``` #### 2. 运动控制模块 ```verilog // 三轴联动控制电路 <电机驱动> TB6600步进驱动器(脉冲输入:PA8-PA10, 方向控制:PB0-PB2) <编码器接口> AM26LS32差分接收器(正交编码器信号处理) <电流检测> INA240电流传感器+STM32 ADC1(采样率1MHz) ``` #### 3. 感知模块 ```cpp // 多维力反馈系统 [压力传感] FlexiForce A201(0-100N) -> AD620放大 -> STM32 ADC3 [位置检测] AS5600磁编码器(I²C接口) -> PB6/PB7 [温度监测] DS18B20(单总线协议) -> PD2 ``` #### 4. 通信模块 ```python # 系统通信架构 -CAN总线: TJA1050T收发器(500kbps速率)连接各执行器 -蓝牙5.0: HC-08模块(AT指令控制)实现手机APP交互 -USB OTG: CH340G转换芯片用于调试数据导出 ``` --- ### **二、软件系统设计** #### 1. 主程序框架(Keil MDK开发) ```c void main() { HAL_Init(); SystemClock_Config(); // 外设初始化 MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM3_Init(); // PWM生成 MX_I2C1_Init(); // 创建FreeRTOS任务 xTaskCreate(TargetLocate_Task, "Locate", 128, NULL, 3, NULL); xTaskCreate(ForceControl_Task, "ForceCtrl", 256, NULL, 4, NULL); vTaskStartScheduler(); } ``` #### 2. 靶点定位算法 ```matlab % 坐标转换模型(极坐标→笛卡尔) function [x,y] = Polar2Cartesian(r,θ) x = r*cos(θ*pi/180) + 0.15*L; % L为足长 y = r*sin(θ*pi/180) - 0.08*W; % W为足宽 end ``` #### 3. 按摩力度PID控制 ```c // 模糊PID控制器实现 float Force_PID(float target_F) { static float errSum=0, lastErr=0; float err = target_F - GetActualForce(); errSum += err * dt; // 积分项 float dErr = (err - lastErr) / dt; // 微分项 // 模糊调节参数(示例) Kp = 2.5 + 0.3*abs(err); Ki = 0.1 * (1 - exp(-0.5*err)); return Kp*err + Ki*errSum + Kd*dErr; } ``` #### 4. 按摩手法程序库 ```c // 典型手法函数(以点按法为例) void Acupressure(uint16_t duration) { SetPressure(25.0f); // 设置目标压力 PWM_SetFreq(1.5f); // 1.5Hz脉冲 for(int i=0; i<duration; i+=500){ MoveToTarget(x,y,z); // 靶点定位 PID_ForceControl(); // 力度闭环 HAL_Delay(500); // 保持500ms } } ``` --- ### **三、关键实现技术** 1. **实时控制优化** - 配置DMA实现ADC多通道同步采样 - 使用TIM定时器硬件PWM生成按摩脉冲 - 中断优先级配置: ``` 压力保护中断(EXTI0) > 电机限位中断(EXTI9_5) > 通信中断 ``` 2. **安全保护机制** ```c // 硬件看门狗电路 void Watchdog_Init(void) { IWDG->KR = 0xCCCC; // 启动独立看门狗 IWDG->KR = 0x5555; IWDG->PR = 4; // 预分频256 IWDG->RLR = 0xFFF; // 超时时间3.2s } ``` 3. **能耗管理** ```c // 动态电源控制策略 void PowerManage(void) { if(State == IDLE) { __HAL_RCC_GPIOB_CLK_DISABLE(); // 关闭未用外设时钟 HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); } } ``` --- ### **四、系统验证方案** 1. **硬件测试** - 使用示波器检测PWM波形(要求频率误差<±2%) - 通过万用表测量电源纹波(<50mVpp) - EMC测试:静电接触放电±8kV不宕机 2. **软件验证** ```test 测试用例示例: 输入:涌泉穴坐标(r=0.2L, θ=120°) 预期输出:X轴移动(72±1)mm,Y轴移动(53±1)mm 实际测量:X=71.8mm,Y=53.2mm ✅ ``` 3. **整机联调** - 建立状态转移图验证工作流程 - 进行连续48小时压力稳定性测试(漂移量<±5%) - 组织10人双盲试验评估按摩效果 该设计方案已考虑EMC兼容性、实时响应性(控制周期≤10ms)、操作安全性等工程要求,建议采用Altium Designer进行四层PCB设计,信号层与电源层分离布置,关键模拟信号走线做包地处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值