STM32F407的CAN通信实验

 

软件:keil5、EmbededDebug v2.0

目的:按下按键芯片能发送给电脑。当电脑发送时,触发中断,而后芯片把收到的数据返回给电脑

 

 

       以下必须有,放入主函数:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2

delay_init(168);    //初始化延时函数

LED_Init(); //初始化LED 

KEY_Init(); //按键初始化  

CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_Normal);//500K

 

while(1)

{

key=KEY_Scan(0);//按键扫描

 if(key==KEY0_PRES)//KEY0按下,发送一次数据

 { 

 for(i=0;i<8;i++) 

 { 

 canbuf[i]=i;//填充发送缓冲区 

   } 

 CAN1_KeySend_Msg(canbuf,8); 

 } 

}

 

使用扩展帧,不用标准帧:

u8 CAN1_KeySend_Msg(u8* msg,u8 len)

{

  u8 mbox;

  u16 i=0;

  CanTxMsg TxMessage;

//TxMessage.StdId=0x18; //  This parameter can be a value between 0 to 0x7FF.  标准的不用了

  TxMessage.ExtId=0x181056f4; // This parameter can be a value between 0 to 0x1FFFFFFF 使用扩展

//TxMessage.IDE=0;  

  TxMessage.IDE=1; //使用扩展置1

  TxMessage.RTR=0;// 消息类型为数据帧

  TxMessage.DLC=len;

  for(i=0;i

  TxMessage.Data[i]=msg[i];  

  mbox= CAN_Transmit(CAN1, &TxMessage);   

  i=0;

  while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;//等待发送结束

  if(i>=0XFFF)return 1;

  return 0;

 

}

 

 

最重要的就是:CAN_Transmit()

 在stm32f4xx_can.c文件中

如果用例程,使用扩展帧的时候一直都失败

所以需要修改的地方如下:

      assert_param(IS_CAN_EXTID(TxMessage->ExtId));

      CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId << 3) | \

                                                  TxMessage->IDE<<2 | \

                                                  TxMessage->RTR<<1);

 

现在自己写一个结构体用来存放自己想发送的数据

typedef struct CAN_Tx{

u16 DA;               //指定发送的数据

u16 DB;

u16 DC;

u16 DD;    

u16 Ide;

u16 Rtr;

u16 Len;                //指定字节数     

u32 RevMBXnID ;         //指定发送的ID号,

}TCAN_Msg;

TCAN_Msg  CANTxMsg[]={{0,0,0,0, 0,0,0,0x00}};

 

再搞一个指针TCAN_Msg *PtrCanTx = &CANTxMsg[0];//指向结构体地址

 

就可以这样了:PtrCanTx-> Len = 8;

 

再写一个和上面u8 CAN1_KeySend_Msg(u8* msg,u8 len)差不多的函数

就叫:u8  CAN1_Send_Msg(TCAN_Msg *CANTx)

 

 

对于中断服务函数:

在初始化的时候(用例程就行)已开启中断,所以电脑发送数据就会触发中断(FIFO0消息挂号中断允许.)

void CAN1_RX0_IRQHandler(void)

在中断中可以写一些,接收到某消息后的某动作啥的

 

================================================================

按键按下发送:0x01 0x02 0x03 0x04 0x05 0x06 0x07

在程序里写想发送的数据:0x01 0x00 0x00 0x00 0x00 0x00

 

STM32F407的CAN通信实验
 

以下是使用HAL库在STM32F407芯片上发送CAN消息的示例代码: ``` #include "stm32f4xx_hal.h" #include "main.h" CAN_HandleTypeDef hcan1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_CAN1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_CAN1_Init(); // 构造CAN消息 CAN_TxHeaderTypeDef TxHeader; uint8_t TxData[8]; TxHeader.StdId = 0x123; // 标准标识符 TxHeader.RTR = CAN_RTR_DATA; // 数据 TxHeader.IDE = CAN_ID_STD; // 标准 TxHeader.DLC = 8; // 数据长度为8字节 TxData[0] = 0x11; TxData[1] = 0x22; TxData[2] = 0x33; TxData[3] = 0x44; TxData[4] = 0x55; TxData[5] = 0x66; TxData[6] = 0x77; TxData[7] = 0x88; // 发送CAN消息 uint32_t TxMailbox; if (HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox) != HAL_OK) { Error_Handler(); } while (1) { } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 50; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } static void MX_CAN1_Init(void) { hcan1.Instance = CAN1; hcan1.Init.Prescaler = 5; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.TimeSeg1 = CAN_BS1_11TQ; hcan1.Init.TimeSeg2 = CAN_BS2_2TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = ENABLE; hcan1.Init.AutoWakeUp = DISABLE; hcan1.Init.AutoRetransmission = ENABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } } void Error_Handler(void) { while (1) { } } ``` 在此示例中,我们使用标准标识符0x123构造了一个8字节的CAN数据,并将其发送到CAN总线上。在MX_CAN1_Init函数中,我们使用了以下CAN初始化配置: - 波特率为1Mbps(钟频率为50MHz,分频系数为5) - 正常模式 - 间段1为11个间单位,间段2为2个间单位 - 自动总线关闭(当总线错误次数超过一定阈值,自动关闭总线) - 自动重传(如果发送失败,自动重传) - 禁止接收FIFO锁定 - 禁止传输FIFO优先级 当我们调用HAL_CAN_AddTxMessage函数发送CAN消息,它会将CAN消息添加到CAN发送FIFO中,并返回用于该消息的邮箱号(TxMailbox)。您可以使用HAL_CAN_GetTxMailboxesFreeLevel函数检查发送FIFO中可用的邮箱数量。如果返回值为0,则发送FIFO已满,您需要等待一段间,或者实现重传机制来处理此问题。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值