历史上的今天
今天是:2024年09月30日(星期一)
2019年09月30日 | cubemx实现CAN通讯
2019-09-30 来源:eefocus
首先要安装cubemx跟Keil5两个编程软件
然后打开cubemx软件,新建一个工程项目:

输入CPU型号:

在右下角双击CPU具体型号

稍等片刻会打开如下对话框:

首先要配置系统的调试方式:我们选择SW方式

然后配置晶振源,这里选择的是外部晶振,8M

使能看门狗

使能CAN

使能TIM2时钟源,采用内部时钟

配置完成后可以看到单片机管脚已经做了配置

切换到Clock Configuration选项卡,配置时钟周期,这里配置为8M

切换到Configuration选项卡,进入CAN配置选项配置波特率如下为500Kbps

配置接收中断

配置定时器如下为1ms定时器

配置定时器中断

配置完成后点击保存,然后点击如下按钮,生成代码

填写工程名称,路径,编程软件等等

选择生成代码的方式

等待

点击打开项目。代码生成部分完成。

添加一些特殊配置和逻辑代码
添加CAN的配置信息函数
void Can_Config(void)
{
hcan.pTxMsg = &TxMessage;
hcan.pRxMsg = &RxMessage;
/*##-1- Configure CAN1 Transmission Massage #####################################*/
hcan.pTxMsg->StdId = 0x123;
hcan.pTxMsg->RTR = CAN_RTR_DATA;
hcan.pTxMsg->IDE = CAN_ID_STD;
hcan.pTxMsg->DLC = 8;
/*##-2- Configure the CAN1 Filter ###########################################*/
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterIdHigh = 0;
sFilterConfig.FilterIdLow = 0;
sFilterConfig.FilterMaskIdHigh = 0;
sFilterConfig.FilterMaskIdLow = 0;
sFilterConfig.FilterFIFOAssignment = CAN_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
}
在Main函数中while(1)之前调用一下即可
添加定时器启动函数: HAL_TIM_Base_Start_IT(&htim2);
CAN接收中断启动函数:HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
/* USER CODE BEGIN 2 */
Can_Config(); //Can配置信息
HAL_TIM_Base_Start_IT(&htim2); //定时器启动
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//使能Can接收中断
/* USER CODE END 2 */
打开stm32f1xx_it.c文件,找到如下函数,
添加接收中断启动函数:HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
注意:接收中断启动函数使能一次只进一次中断,所以中断退出前要再次使能。
void USB_LP_CAN1_RX0_IRQHandler(void)
{
/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */
/* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan);
/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//ʹÄÜCAN½ÓÊÕ
/* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */
}
添加CAN接收服务函数:HAL_CAN_RxCpltCallback
说明:该函数在stm32f1xx_hal_can.c文件中已经有定义,它的定义方式如下:
__weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
函数前面的__weak关键字意思是如果有同样的定义,先执行没有__weak关键字的函数,所以当我们定义了HAL_CAN_RxCpltCallback函数后,编译器会先编译我们定义的函数,而忽略系统定义的该函数。当我们没有定义该函数时,系统会编译带有__weak关键字的函数。
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
{
unsigned short int speed;
switch(hcan->pRxMsg->StdId)
{//根据ID处理数据
case 0x123://
/*在此添加数据处理逻辑*/
break;
default:
break;
}
}
添加CAN发送函数:
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_IWDG_Refresh(&hiwdg); //喂狗函数
if(Can_Trans_Timer == 0)
{//每100ms发送一次数据
Can_Trans_Timer = 100;
hcan.pTxMsg->StdId = 0x123;
hcan.pTxMsg->Data[0] = 'C';
hcan.pTxMsg->Data[1] = 'A';
hcan.pTxMsg->Data[2] = 'N';
hcan.pTxMsg->Data[3] = ' ';
hcan.pTxMsg->Data[4] = 'T';
hcan.pTxMsg->Data[5] = 'E';
hcan.pTxMsg->Data[6] = 'S';
hcan.pTxMsg->Data[7] = 'T';
HAL_CAN_Transmit(&hcan, 200);//发送一帧数据
}
}
/* USER CODE END WHILE */
在定时器函数中添加定时器代码:
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
if(Can_Trans_Timer > 0) Can_Trans_Timer--;
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
}
说明:在往工程中添加代码时要注意,不要任意往里面添加代码,要在注释着USER CODE BEGIN的地方添加代码,这样在重新生成代码时才不至于将已经写好的代码覆盖掉,如下
/* USER CODE BEGIN Includes */
添加用户代码
/* USER CODE END Includes */
/* USER CODE BEGIN PFP */
添加用户代码
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
添加用户代码
/* USER CODE END 0 */
史海拾趣
|
AVR ATMega16 步进电机驱动程序,已经调试通过【转】 这两天做步进电机的驱动成功,现将程序共享,愿起到抛砖引玉的作用。 此程序可驱动五引线步进电机,通过按键可控制步进电机的转速、方向、三种驱动方式,三种驱动方式分别为:单四拍驱动、双四拍驱动、单双八拍驱动,其中以单双八拍驱动转速最慢。 ...… 查看全部问答> |
|
上述代码经过在Quartus II上编译仿真后其波形如图2所示。 设计中适当选取K值特别的重要。如果K值偏大,这样计数器对少量噪声干扰不可能计满,就不会有进位或者借位脉冲,有利于抑制随机噪声;但就会使捕捉带减小,导致环路进入锁定 ...… 查看全部问答> |
|
用三星的dnw下载eboot和nk,不小心把机器整蓝屏了,于是我就直接关掉插座的电源(不是关的pc的power键)。然后重新上电开机。开机后dnw就不能打开了,弹出“ dnw.exe 遇到问题需要关闭。我们对此引起的不便表示抱歉”这个需要进入调试和发送错误报 ...… 查看全部问答> |
|
找了不少资料,造成这样的原因应该是按键按下和弹起都会触发消息。 但是,怎么避免呢 在vc下,有的做法是在hook过程函数处理之前加个判断,那些我没试过行不行。 但是在wince下用如下方法判断却都不行。郁闷! if (LLKHF_UP==(keyb->flags) ) ...… 查看全部问答> |




