- 3508、2006电机在各种比赛的使用很遍及,其电调驱动方式有PWM和CAN两种,我用的是CAN,在此分享一下个人的学习心得;
复制代码
步伐部门主要分三部门:
STM32F104的CAN通信配置
- void CAN1_Configuration(void){ GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //使能CAN1时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA11,PA12 GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1 CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); CAN_InitStructure.CAN_TTCM= DISABLE; //非时间触发通信模式 CAN_InitStructure.CAN_ABOM= DISABLE; //软件自动离线管理 CAN_InitStructure.CAN_AWUM= DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART= ENABLE; //克制报文自动传送 CAN_InitStructure.CAN_RFLM= DISABLE; //报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP= DISABLE; //优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= CAN_Mode_Normal; //模式设置 CAN_InitStructure.CAN_SJW= CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1= CAN_BS1_9tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2= CAN_BS2_4tq; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler= 3; //分频系数(Fdiv)为brp+1 CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1 CAN_FilterInitStructure.CAN_FilterNumber= 0; //过滤器0 CAN_FilterInitStructure.CAN_FilterMode= CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale= CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh= 0x0000; //32位ID CAN_FilterInitStructure.CAN_FilterIdLow= 0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0x0000; //32位MASK CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment= CAN_Filter_FIFO0; //过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation= ENABLE; //激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化 CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许 CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}void CAN2_Configuration(void){ GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); //使能CAN1时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB12,PB13 GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_CAN2); //GPIOB12复用为CAN2 GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_CAN2); //GPIOB13复用为CAN2 CAN_DeInit(CAN2); CAN_StructInit(&CAN_InitStructure); CAN_InitStructure.CAN_TTCM= DISABLE; //非时间触发通信模式 CAN_InitStructure.CAN_ABOM= DISABLE; //软件自动离线管理 CAN_InitStructure.CAN_AWUM= DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN_InitStructure.CAN_NART= ENABLE; //克制报文自动传送 CAN_InitStructure.CAN_RFLM= DISABLE; //报文不锁定,新的覆盖旧的 CAN_InitStructure.CAN_TXFP= DISABLE; //优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= CAN_Mode_Normal; //模式设置 CAN_InitStructure.CAN_SJW= CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq CAN_InitStructure.CAN_BS1= CAN_BS1_9tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq CAN_InitStructure.CAN_BS2= CAN_BS2_4tq; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq CAN_InitStructure.CAN_Prescaler= 3; //分频系数(Fdiv)为brp+1 CAN_Init(CAN2, &CAN_InitStructure); // 初始化CAN1 CAN_FilterInitStructure.CAN_FilterNumber= 14; //过滤器0 CAN_FilterInitStructure.CAN_FilterMode= CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale= CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh= 0x0000; //32位ID CAN_FilterInitStructure.CAN_FilterIdLow= 0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0x0000; //32位MASK CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment= CAN_Filter_FIFO0; //过滤器0关联到FIFO0 CAN_FilterInitStructure.CAN_FilterActivation= ENABLE; //激活过滤器0 CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化 CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE); //FIFO0消息挂号中断允许 CAN_ITConfig(CAN2,CAN_IT_TME,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 主优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}/* CAN1 TX IRQ */void CAN1_TX_IRQHandler(void){ if(CAN_GetITStatus(CAN1,CAN_IT_TME)!= RESET) { CAN_ClearITPendingBit(CAN1,CAN_IT_TME); }}/* CAN1 RX IRQ */void CAN1_RX0_IRQHandler(void){}/* CAN2 TX IRQ */void CAN2_TX_IRQHandler(void){ if(CAN_GetITStatus(CAN2,CAN_IT_TME)!= RESET) { CAN_ClearITPendingBit(CAN2,CAN_IT_TME); }}/* CAN2 RX IRQ */void CAN2_RX0_IRQHandler(void){ }
复制代码 接收数据的步伐
[code]void Motor_ReadData(void) //反馈{ CanRxMsg rx_message; if (CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET) { CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0); CAN_Receive(CAN1, CAN_FIFO0, &rx_message); if(rx_message.StdId == MOTOR_ID_READ1) {// memcpy(&MOTOR_FEEDBACK.angle_value , &rx_message.Data[0], 2);// memcpy(&MOTOR_FEEDBACK.speed_rpm , &rx_message.Data[2], 2);// memcpy(&MOTOR_FEEDBACK.real_current , &rx_message.Data[4], 2);// memcpy(&MOTOR_FEEDBACK.temperature , &rx_message.Data[6], 1); MOTOR_FEEDBACK[motor_1].angle_value = rx_message.Data[0] |