codingtuzi 发表于 2023-4-16 20:33:30

【N32电机控制大赛】基于N32G455的交互式手柄钥匙

本帖最后由 codingtuzi 于 2023-4-16 20:34 编辑

【N32电机控制大赛】基于N32G455的交互式手柄钥匙

背景介绍:在工业智能制造中,机械装置越来越多地应用于车间,场矿。随之带来的操作人员权限认证与操作记录保存的需求也就日益突出。非法人员,未授权人员使用机器进行违规,危险操作;操作人员违反操作手册操作,事后追究,事故分析等问题很难清晰理清。现有权鉴方式多为传统的机械钥匙,存在易丢失,易冒用,无法追踪等风险,而对日志记录功能,基本处于空缺状态。基于上述背景,本次项目实验设计利用国民技术加密算法库完成操作人员权限管理,利用N32G455芯片丰富的外设通讯能力操控目标设备。方案简介:1.       由单一操控的手柄升级为可操作,可认证的手柄钥匙;2.       使用CAN 2.0B外设与目标控制器通讯,完成目标设备的待机与实时操作;3.       双摇杆与按键联合,保留了易操作性,便于操作人员上手使用;4.       兼具数据记录仪功能,类似事故的“黑匣子”可用于现场回放;5.       通过N32板载的加密算法,实现人员认证与权限管理方案亮点:1.       在MCU中使用非对称加密方式加密密钥,不会泄露密码数据2.       丰富的外设,如CAN 2.0和RS485物理层协议3.       可对操作指令进行数据保存,可通过AES对称方式加密保存4.       在强大的安全加密算法下,数据以低成本的TF卡形式保存。有效降低部署成本,让追溯更易普及硬件设计框图硬件模块设计摇杆在对需求做市场调研时,对于机械手臂的操作,最常用的即为摇杆,操作幅度,力馈均可以较好的给操作人员带来便捷与稳定的控制。另外一种,类似于虚拟现实中的手套,体验感与科技感十足,但成本与技术门槛较高。本次设计中,采用指控摇杆的方案,成本与技术均可,体验感又保持在一定高度。双轴摇杆采用103电位器开关实现,在设计中使用两路ADC对电压进行采集。
功能引脚备注
摇杆x轴PC0

摇杆y轴PC1


CAN外设对于电机控制,首选CAN通讯。养分信号的物理层协议可以屏蔽掉共模信号的干扰。CAN 2.0B的高带宽,又可以满足电机控制的实时与高精度控制。CAN控制器的Filter功能又可以最大限度的减少总线数据的影响,MCU也更专注于处理算法,专注于处理自己相关的控制信息。RS485通讯在本次设计中,保留了低速,低成本的RS485通讯方案。此方案预留主要目的在对控制器进行固件升级,控制器配置数据更新等操作。可以将控制器连接到物联网,网关等边缘设备上。SPI外设(SDIO外设)本次设计中有一项为日志的数据保存。对SD卡的读写物理层上驱动可以选用SDIO和SPI两种模式。考虑时间与精力上的原因,第一阶段实现SPI模式的驱动;第二阶段再实现SDIO模式。
功能引脚备注
SPI1 MOSIPA5

SPI1 SCLKPA7

SPI1 MISOPA6

SD selectPA4


软件模块设计本次软件架构相对简单,使用FreeRTOS嵌入式操作系统,来实现所有需求。任务划分根据设计需求,我本次将任务划分如下:l按键和摇杆,两者均是对电机的操作,只是采样形式不同,因此划分在同一个任务之中。以周期20ms采样,并进行滤波与去抖算法lCAN通讯发送,在人机交互过程中,在对按键进行采集确认后,通过队列的方式接收按键键码与数值,进行封装后在CAN总线网络上发送lCAN通讯接收,接收到设备的数据。将有效数据收集后,转存到TF卡按键和摇杆摇杆采集的为模拟量,因此,在本次设计上,以阶段阈值的方式实现,即分为3档速度。void bsp_adc_init(void)
{
GPIO_InitType GPIO_InitStructure;
ADC_InitType ADC_InitStructure;

RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1, ENABLE);
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8);

/* Configure PC0 PC1 as analog input -------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);

/* ADC configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC1, &ADC_InitStructure);

/* Enable ADC */
ADC_Enable(ADC1, ENABLE);
/*Check ADC Ready*/
while (ADC_GetFlagStatusNew(ADC1, ADC_FLAG_RDY) == RESET)
    ;
/* Start ADC calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC calibration */
while (ADC_GetCalibrationStatus(ADC1))
    ;
}
CAN通讯
使用CAN1外设,设置500kbps的标准帧模式void bsp_can_init(void)
{
GPIO_InitType GPIO_InitStructure;
CAN_InitType CAN_InitStructure;

GPIO_ConfigPinRemap(GPIO_RMP1_CAN2, ENABLE);

/* Configure CAN1 RX pin */
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
/* Configure CAN1 TX pin */
GPIO_InitStructure.Pin = GPIO_PIN_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN2, ENABLE);
/* CAN register init */
CAN_DeInit(CAN2);
/* Struct init*/
CAN_InitStruct(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.TTCM = DISABLE;
CAN_InitStructure.ABOM = DISABLE;
CAN_InitStructure.AWKUM = DISABLE;
CAN_InitStructure.NART = DISABLE;
CAN_InitStructure.RFLM = DISABLE;
CAN_InitStructure.TXFP = ENABLE;
CAN_InitStructure.OperatingMode = OPERATINGMODE;
CAN_InitStructure.RSJW = CAN_BIT_RSJW;
CAN_InitStructure.TBS1 = CAN_BIT_BS1;
CAN_InitStructure.TBS2 = CAN_BIT_BS2;
CAN_InitStructure.BaudRatePrescaler = CAN_BAUDRATEPRESCALER; // 500K
/*Initializes the CAN */
CAN_Init(CAN1, &CAN_InitStructure);
CAN_Filter_Init();
CAN_NVIC_Config();
}
RS485通讯void bsp_usart_init(void)
{

USART_InitType USART_InitStructure;
GPIO_InitType GPIO_InitStructure;
NVIC_InitType NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

uart_rx.length = 0;
uart_rx.state = rx_state_idle;
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

// RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO, ENABLE);
/* Enable USARTy and USARTz Clock */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);

/* Configure USARTx Tx as alternate function push-pull */
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

/* Configure USARTx Rx as input floating */
GPIO_InitStructure.Pin = GPIO_PIN_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

/* USARTy and USARTz configuration ------------------------------------------------------*/
USART_InitStructure.BaudRate = 9600;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;

// USART_ConfigInt(USART1, USART_INT_RXDNE, ENABLE);
// USART_ConfigInt(USART1, USART_INT_IDLEF, ENABLE);

/* Configure USARTx */
USART_Init(USART1, &USART_InitStructure);
/* Enable the USARTx */
USART_Enable(USART1, ENABLE);
}
SPI通讯
SD卡操作状态流转图:

void bsp_spi_init(void)
{
GPIO_InitType GPIO_InitStructure;
SPI_InitType SPI_InitStructure;
/* PCLK2 = HCLK/2 */
RCC_ConfigPclk2(RCC_HCLK_DIV2);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_SPI1 | RCC_APB2_PERIPH_AFIO, ENABLE);

/* Configure SPIy pins: SCK, MISO and MOSI ---------------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.Pin = GPIO_PIN_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

/* SPI1 Config -------------------------------------------------------------*/
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_256;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Init(SPI1, &SPI_InitStructure);

/* Enable SPIy */
SPI_Enable(SPI1, ENABLE);
}
实物照片








页: [1]
查看完整版本: 【N32电机控制大赛】基于N32G455的交互式手柄钥匙