【软件设计】
CAN引脚初始化
/*
* 函数名:CAN_GPIO_Config
* 描述 :CAN的GPIO 配置
* 输入 :无
* 输出 : 无
* 调用 :内部调用
*/
static void CAN_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIO clock */
RCC_APB2PeriphClockCmd(CAN_TX_GPIO_CLK | CAN_RX_GPIO_CLK, ENABLE);
//重映射引脚
GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
/* Configure CAN TX pins */
GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);
/* Configure CAN RX pins */
GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
}
CAN中断优先级配置
/*
* 函数名:CAN_NVIC_Config
* 描述 :CAN的NVIC 配置,第1优先级组,0,0优先级
* 输入 :无
* 输出 : 无
* 调用 :内部调用
*/
static void CAN_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*中断设置*/
NVIC_InitStructure.NVIC_IRQChannel = CAN_RX_IRQ; //CAN1 RX0中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
CAN模式配置
/*
* 函数名:CAN_Mode_Config
* 描述 :CAN的模式 配置
* 输入 :无
* 输出 : 无
* 调用 :内部调用
*/
static void CAN_Mode_Config(void)
{
CAN_InitTypeDef CAN_InitStructure;
/************************CAN通信参数设置**********************************/
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
/*CAN寄存器初始化*/
CAN_DeInit(CANx);
CAN_StructInit(&CAN_InitStructure);
/*CAN单元初始化*/
CAN_InitStructure.CAN_TTCM = DISABLE; //MCR-TTCM 关闭时间触发通信模式使能
CAN_InitStructure.CAN_ABOM = ENABLE; //MCR-ABOM 自动离线管理
CAN_InitStructure.CAN_AWUM = ENABLE; //MCR-AWUM 使用自动唤醒模式
CAN_InitStructure.CAN_NART = DISABLE; //MCR-NART 禁止报文自动重传 DISABLE-自动重传
CAN_InitStructure.CAN_RFLM = DISABLE; //MCR-RFLM 接收FIFO 锁定模式 DISABLE-溢出时新报文会覆盖原有报文
CAN_InitStructure.CAN_TXFP = DISABLE; //MCR-TXFP 发送FIFO优先级 DISABLE-优先级取决于报文标示符
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //正常工作模式
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; //BTR-SJW 重新同步跳跃宽度 2个时间单元
/* ss=1 bs1=9 bs2=8 位时间宽度为(1+8+9) 波特率即为时钟周期tq*(1+8+9) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq; //BTR-TS1 时间段1 占用了9个时间单元
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq; //BTR-TS1 时间段9 占用了8个时间单元
/* CAN Baudrate = 1 MBps (1MBps已为stm32的CAN最高速率) (CAN 时钟频率为 APB1 = 36 MHz) */
CAN_InitStructure.CAN_Prescaler = 48; BTR-BRP 波特率分频器 定义了时间单元的时间长度 36/(1+8+9)/4= 0.5 Mbps
CAN_Init(CANx, &CAN_InitStructure);
}
CAN过滤器配置
/*
* 函数名:CAN_Filter_Config
* 描述 :CAN的过滤器 配置
* 输入 :无
* 输出 : 无
* 调用 :内部调用
*/
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN筛选器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber = 0; //筛选器组0
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; //工作在掩码模式
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //筛选器位宽为单个32位。
/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
//标准数据帧的配置
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)0x45<<21)&0xffff0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)0x45<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
//扩展数据帧的配置
// CAN_FilterInitStructure.CAN_FilterIdHigh = ((((u32)0x45 << 3) | CAN_ID_STD | CAN_RTR_DATA) & 0xFFFF0000) >> 16; //要筛选的ID高位
// CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)0x45 << 3) | CAN_ID_STD | CAN_RTR_DATA) & 0xFFFF; //要筛选的ID低位
// CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF; //筛选器高16位每位必须匹配
// CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF; //筛选器低16位每位必须匹配
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; //筛选器被关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能筛选器
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}
CAN整合配置
/*
* 函数名:CAN_Config
* 描述 :完整配置CAN的功能
* 输入 :无
* 输出 : 无
* 调用 :外部调用
*/
void CAN_Config(void)
{
CAN_GPIO_Config();
CAN_NVIC_Config();
CAN_Mode_Config();
CAN_Filter_Config();
}
初始化 RxMessage数据结构体
/**
* @brief 初始化 RxMessage数据结构体
* @param RxMessage: 指向要初始化的数据结构体
* @retval None
*/
void Init_RxMes(CanRxMsg *RxMessage)
{
uint8_t ubCounter = 0;
/*把接收结构体清零*/
RxMessage->StdId = 0x00;
RxMessage->ExtId = 0x00;
RxMessage->IDE = CAN_ID_STD;
RxMessage->DLC = 0;
RxMessage->FMI = 0;
for (ubCounter = 0; ubCounter < 8; ubCounter++)
{
RxMessage->Data[ubCounter] = 0x00;
}
}
设置CAN_SetMsg
/*
* 函数名:CAN_SetMsg
* 描述 :CAN通信报文内容设置,设置一个数据内容为0-7的数据包
* 输入 :发送报文结构体
* 输出 : 无
* 调用 :外部调用
*/
void CAN_SetMsg(CanTxMsg *TxMessage)
{
// uint8_t ubCounter = 0;
TxMessage->StdId=0x45; //使用的标准ID
//TxMessage->ExtId = 0x45;
TxMessage->IDE = CAN_ID_STD; //标准模式
TxMessage->RTR = CAN_RTR_DATA; //发送的是数据
TxMessage->DLC = 8; //数据长度为8字节
/*设置要发送的数据0-7*/
// for (ubCounter = 0; ubCounter < 8; ubCounter++)
// {
// TxMessage->Data[ubCounter] = ubCounter;
// }
TxMessage->Data[0] = 0;
TxMessage->Data[1] = speedct*1000;
TxMessage->Data[2] = poct*1000;
TxMessage->Data[3] = 0;
TxMessage->Data[4] = 0;
TxMessage->Data[5] = 0;
TxMessage->Data[6] = 0;
TxMessage->Data[7] = 0;
}
CAN接受中断服务
/*
* 函数名:USB_LP_CAN1_RX0_IRQHandler
* 描述 :USB中断和CAN接收中断服务程序,USB跟CAN公用I/O,这里只用到CAN的中断。
* 输入 :无
* 输出 : 无
* 调用 :无
*/
void CAN_RX_IRQHandler(void)
{
/*从邮箱中读出报文*/
CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
/* 比较ID是否为0x1314 */
if((RxMessage.StdId==0x45) && (RxMessage.IDE==CAN_ID_STD) && (RxMessage.DLC==8) )
{
flag = 1; //接收成功
}
else
{
flag = 0; //接收失败
}
}
主函数
int main(void)
{
MY_NVIC_PriorityGroupConfig(2); //=====设置中断分组
delay_init(); //=====延时函数初始化
KEY_Init(); //=====按键初始化
usart1_init(115200); //=====串口1初始化
CAN_Config(); /*初始化can,在中断接收CAN数据包*/
MiniBalance_PWM_Init(7199, 0); //=====初始化PWM 10KHZ,用于驱动电机 如需初始化电调接口
TIM5_Cap_Init(0XFFFF,72-1); //=====超声波始化 默认注释 超声波接线 参考timer.h文件
TIM3_Cap_Init(0XFFFF,72-1); //=====超声波始化 默认注释 超声波接线 参考timer.h文件
while(1)
{
/*设置要发送的报文*/
CAN_SetMsg(&TxMessage);
/*把报文存储到发送邮箱,发送*/
CAN_Transmit(CANx, &TxMessage);
can_delay(10000);//等待发送完毕,可使用CAN_TransmitStatus查看状态
if(flag==1)
{
printf("\r\nCAN接收到数据:\r\n");
CAN_DEBUG_ARRAY(RxMessage.Data,8);
x = RxMessage.Data[0];
ang = RxMessage.Data[1];
flag=0;
}
}
}
CAN头文件
#ifndef __CAN_H
#define __CAN_H
#include "stm32f10x.h"
#include "usart.h"
#define CANx CAN1
#define CAN_CLK RCC_APB1Periph_CAN1
#define CAN_RX_IRQ USB_LP_CAN1_RX0_IRQn
#define CAN_RX_IRQHandler USB_LP_CAN1_RX0_IRQHandler
#define CAN_RX_PIN GPIO_Pin_8
#define CAN_TX_PIN GPIO_Pin_9
#define CAN_TX_GPIO_PORT GPIOB
#define CAN_RX_GPIO_PORT GPIOB
#define CAN_TX_GPIO_CLK (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB)
#define CAN_RX_GPIO_CLK RCC_APB2Periph_GPIOB
/*debug*/
#define CAN_DEBUG_ON 1
#define CAN_DEBUG_ARRAY_ON 1
#define CAN_DEBUG_FUNC_ON 1
// Log define
#define CAN_INFO(fmt, arg...) printf("<<-CAN-INFO->> " fmt "\n", ##arg)
#define CAN_ERROR(fmt, arg...) printf("<<-CAN-ERROR->> " fmt "\n", ##arg)
#define CAN_DEBUG(fmt, arg...) \
do \
{ \
if (CAN_DEBUG_ON) \
printf("<<-CAN-DEBUG->> [%d]" fmt "\n", __LINE__, ##arg); \
} while (0)
#define CAN_DEBUG_ARRAY(array, num) \
do \
{ \
int32_t i; \
float *a = array; \
if (CAN_DEBUG_ARRAY_ON) \
{ \
printf("<<-CAN-DEBUG-ARRAY->>\n"); \
for (i = 0; i < (num); i++) \
{ \
printf("%f ", (a)[i]); \
if ((i + 1) % 10 == 0) \
{ \
printf("\n"); \
} \
} \
printf("\n"); \
} \
} while (0)
#define CAN_DEBUG_FUNC() \
do \
{ \
if (CAN_DEBUG_FUNC_ON) \
printf("<<-CAN-FUNC->> Func:%s@Line:%d\n", __func__, __LINE__); \
} while (0)
static void CAN_GPIO_Config(void);
static void CAN_NVIC_Config(void);
static void CAN_Mode_Config(void);
static void CAN_Filter_Config(void);
void CAN_Config(void);
void CAN_SetMsg(CanTxMsg *TxMessage);
void Init_RxMes(CanRxMsg *RxMessage);
#endif
在下菜鸟,大家的鼓励是我继续创作的动力,如果觉得写的不错,欢迎关注,点赞,收藏,转发,谢谢!