完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
1 博客内容
博客内容基于STM32F103 RET6芯片(Keil.STM32F1xx_DFP.2.3.0.pack)+PCA82C250,使用CAN通讯环回模式测试CAN收发。CAN引脚对应PA11(RX)和PA12(TX),使用PB11电压测试数据是否成功。实际测试中PB11输出正常,但PA11和PA12异常,接示波器排查判断PCA82C250硬件故障。 2 STM32芯片、TJA1050、上位机 STM32芯片引脚电平为3.3V,而CAN逻辑电压为0和2.5V。因此STM32芯片和CAN解析器(eg:周立功_USBCAN/Vector_CANape)之间需要收发器,将TTL电平转CAN逻辑电压。本文使用的收发器为PCA82C250,其中TJA1050和PCA82C250可以相互替换。 3 CAN环回模式、轮询/中断接收模式 CAN环回模式用于CAN测试,对外发送同时自己接收。 CAN接收理解两种模式:
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber) { uint8_t message_pending=0; /* Check the parameters */ assert_param(IS_CAN_ALL_PERIPH(CANx)); assert_param(IS_CAN_FIFO(FIFONumber)); if (FIFONumber == CAN_FIFO0) { message_pending = (uint8_t)(CANx->RF0R&(uint32_t)0x03); } else if (FIFONumber == CAN_FIFO1) { message_pending = (uint8_t)(CANx->RF1R&(uint32_t)0x03); } else { message_pending = 0; } return message_pending; } 4 程序原理 CAN对外发送(TX)标准ID为0x11的数据帧,长度为2个字节(内容为0xCA,0xFE)。对接收(RX)内容进行判断,如果全部正确,PB11高电平(实际该引脚连接接示波器,未连接LED)。 if (RxMessage.StdId!=0x11) { return 0; } if (RxMessage.IDE!=CAN_ID_STD) { return 0; } if (RxMessage.DLC!=2) { return 0; } if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE) { return 0; } 5 主程序(Main.c) //================================================ // 名称: Main.c // 作者: Morven_X // 版本: 1.1 // 编制: 2021/03/5 23:55 // 更新: 2021/03/08 20:37 // 功能: 基于STM32F103 RET6芯片,使用CAN发送和接收信息 // 简介: 使用回环模式查看CAN发送,使用USBCAN接收数据(失败) // Email: morven_xie@163.com //================================================ # include "stm32f10x.h" # include "stm32f10x_gpio.h" # include "stm32f10x_can.h" # include "Delay.h" # include "CAN.h" int main(void) { LED_Init(); LED_PB_Init(); Delay_Init(); CAN_GPIO_Init(); NVIC_Configuration(); JTAG_Init(); /* Turns selected LED Off */ LED_Off_PB11; LED_Off_PB12; LED_Off_PB13; LED_Off_PB14; int i; int TestRx; while (1) { /* CAN transmit at 125Kb/s and receive by polling in loopback mode */ TestRx = CAN1_Polling(); if (TestRx == 0) { /* Faild to turn on led PB13 */ LED_On_PB13; } else { /*Success to turn on PB11 */ LED_On_PB11; } /*PC3-LED_ON */ LED_On; Delay_ms(100); // while(i < 0xFFFFF) // { // i++; // } LED_Off_PB11; LED_Off_PB12; LED_Off; // while(i >0x01) // { // i--; // } Delay_ms(100); } } 6 CAN程序(CAN.c) # include "stm32f10x_rcc.h" # include "stm32f10x_gpio.h" # include "CAN.h" void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能C口GPIO时钟 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //选择推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_6; //指定引脚3 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //设置输出速率50MHz// GPIO_Init(GPIOC,&GPIO_InitStruct); //初始化外设GPIOx寄存器 } void LED_PB_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能B口GPIO时钟 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //选择推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; //指定引脚 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //设置输出速率50MHz// GPIO_Init(GPIOB,&GPIO_InitStruct); //初始化外设GPIOx寄存器 } void CAN_GPIO_Init(void) { //**********GPIO初始化**********// GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能A口GPIO时钟 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11 ; //指定引脚PA11,CAN_RX上拉输入 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //设置输出速率50MHz// GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU; //选择上拉输入 GPIO_Init(GPIOA,&GPIO_InitStruct); //初始化外设GPIOA寄存器 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12 ; //指定引脚PA12,CAN_TX复用推挽 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //设置输出速率50MHz// GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //选择推挽输出 GPIO_Init(GPIOA,&GPIO_InitStruct); //初始化外设GPIOA寄存器 } /** * @brief Configures the NVIC and Vector Table base address. * @param None * @retval None */ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void JTAG_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //先开启开启AFIO复用时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能GPIOB外设时钟 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭JTAG,保留SWD(若同时关闭SWD,芯片作废) } int CAN1_Polling(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; CanTxMsg TxMessage; CanRxMsg RxMessage; uint32_t i = 0; uint8_t TransmitMailbox = 0; /* CAN register init */ CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE; CAN_InitStructure.CAN_ABOM=DISABLE; CAN_InitStructure.CAN_AWUM=DISABLE; CAN_InitStructure.CAN_NART=DISABLE; CAN_InitStructure.CAN_RFLM=DISABLE; CAN_InitStructure.CAN_TXFP=DISABLE; CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; /* Baudrate = 125kbps*/ CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_2tq; CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; CAN_InitStructure.CAN_Prescaler=48; CAN_Init(CAN1, &CAN_InitStructure); /* CAN filter init */ CAN_FilterInitStructure.CAN_FilterNumber=0; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); /* transmit */ TxMessage.StdId=0x11; TxMessage.RTR=CAN_RTR_DATA; TxMessage.IDE=CAN_ID_STD; TxMessage.DLC=2; TxMessage.Data[0]=0xCA; TxMessage.Data[1]=0xFE; TransmitMailbox=CAN_Transmit(CAN1, &TxMessage); i = 0; while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFFFF)) { i++; } i = 0; while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFFFF)) { i++; } /* receive */ RxMessage.StdId=0x00; RxMessage.IDE=CAN_ID_STD; RxMessage.DLC=0; RxMessage.Data[0]=0x00; RxMessage.Data[1]=0x00; CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); if (RxMessage.StdId!=0x11) { return 0; } if (RxMessage.IDE!=CAN_ID_STD) { return 0; } if (RxMessage.DLC!=2) { return 0; } if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE) { return 0; } return 1; /* Test Passed */ } 7 CAN头文件(CAN.h) #ifndef _CAN_H #define _CAN_H void LED_Init(void); void LED_PB_Init(void); void NVIC_Configuration(void); void CAN_GPIO_Init(void); void JTAG_Init(void); int CAN1_Polling(void); #define LED_On GPIO_SetBits(GPIOC,GPIO_Pin_3) ; #define LED_On_PB11 GPIO_SetBits(GPIOB,GPIO_Pin_11) ; #define LED_On_PB12 GPIO_SetBits(GPIOB,GPIO_Pin_12) ; #define LED_On_PB13 GPIO_SetBits(GPIOB,GPIO_Pin_13) ; #define LED_On_PB14 GPIO_SetBits(GPIOB,GPIO_Pin_14) ; #define LED_Off_PB11 GPIO_ResetBits(GPIOB,GPIO_Pin_11) ; #define LED_Off_PB12 GPIO_ResetBits(GPIOB,GPIO_Pin_12) ; #define LED_Off_PB13 GPIO_ResetBits(GPIOB,GPIO_Pin_13) ; #define LED_Off_PB14 GPIO_ResetBits(GPIOB,GPIO_Pin_14) ; #define LED_Off GPIO_ResetBits(GPIOC,GPIO_Pin_3) ; #endif |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1117 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1143 浏览 1 评论
575 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
430 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1032 浏览 2 评论
1614浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
281浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
291浏览 3评论
276浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
253浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-20 22:00 , Processed in 0.767471 second(s), Total 47, Slave 41 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号