/*CAN总线实验 采用回环测试
开发板通过CAN总线发送0xAB,0xCD,自己发送自己接收
CAN 所需GPIO不使用重映射 回环测试无需外接导线适用一块开发板测试
*/
#include"stm32f10x.h"
#include <stdio.h>
CanTxMsg TxMessage; //CAN发送缓冲区
CanRxMsg RxMessage; //CAN接收缓冲区
int flag=0xff; //判断接收标志
/*GPIO设置
*/
GPIO_Configuration() //GPIO的设置 CAN发送接收引脚设置
{ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //选中第12引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速率为50MHz
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU; //设置输出方式为上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //取GPIO为GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //选中第11引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速率为50MHz
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP; //设置输出方式为推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //取GPIO为GPIOA
}
void Dealy_Ms(u16 x) //延时
{int i,j;
for(i=0;i<1000;i++)
for(j=0;j<x;j++);
}
int fputc(int ch,FILE *f) //将printf函数指向USART1 发送数据时便可直接调用printf
{USART1->SR;
USART_SendData(USART1, ch); //ch送给USART1
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET); //等待发送完毕
return ch; //返回ch
}
/*UART1发送函数
*/
USART1_Configuration() //usart1串口设置
{USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE); //usart1串口时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选中第9引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速率为50MHz
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP; //设置输出方式为复用输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选中第10引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速率为50MHz
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING; //设置输出方式为模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_DeInit(USART1); //初始化
USART_InitStructure.USART_BaudRate = 9600; //9600波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //八个字节
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位为1位
USART_InitStructure.USART_Parity = USART_Parity_No; //无校验
USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //无硬件流
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //接收和发送功能使能
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); //串口使能
}
/*
CAN总线的模式初始化
*/
void CAN_Mode_Configriation(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_DeInit(CAN1); //CAN总线寄存器初始化
CAN_StructInit(&CAN_InitStructure); //CAN单元初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE); //开启CAN总线时钟
CAN_InitStructure.CAN_TTCM = DISABLE; //关闭时间时间触发通信
CAN_InitStructure.CAN_ABOM = ENABLE; //开启自动离线管理
CAN_InitStructure.CAN_AWUM = ENABLE; //开启自动唤醒模式
CAN_InitStructure.CAN_NART = DISABLE; //开启禁止报文自动重传
CAN_InitStructure.CAN_RFLM = DISABLE; //开启接收FIFO锁定模式 DISABLE设置为溢出时新报文覆盖原有报文
CAN_InitStructure.CAN_TXFP = DISABLE; //发送FIFO优先级DISABLE设置为优先级取决于报文标识符ENABLE设置为顺序优先级
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack; // 设置工作模式为回环测试一块开发板无需接任何线
CAN_InitStructure.CAN_SJW = CAN_BS1_2tq; //重新同步跳跃宽度为2个时间单元
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq; //BTR-TS1时间段1占用6个时间单元
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; //BTR-TS1时间段2占用3个时间单元
CAN_InitStructure.CAN_Prescaler =4; //BTR-BRP波特率分频器 定义时间单元的时间大小
//APB1的时钟频率为36M则传输速率为36/(1+3+6)/4=0.8Mbps
CAN_Init(CAN1,&CAN_InitStructure);
}
/*
CAN的过滤器设置
*/
void CAN_Filter_Configriation(void)
{ CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber = 2; //设置过滤器组2
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; //工作在标识位屏蔽模式
//让报文标识符过滤器按照报文的内容进行对比过滤拓展ID不符合就抛弃
//符合就存入FIFO0
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //过滤器位宽为单位32个
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)0x1225<<3)&0xffff0000)>>16; //过滤的拓展ID的高16位
CAN_FilterInitStructure.CAN_FilterIdLow = ((u32)0x1225<<3)|CAN_ID_EXT|CAN_RTR_DATA&0XFFFF; //过滤的ID低16位
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_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); //CAN通信中断使能
}
/*
主机的通信报文设置
*/
void CAN_SETMsg(void)
{ TxMessage.ExtId=0x1225; //报文的拓展ID设置
TxMessage.IDE = CAN_ID_EXT; //拓展模式
TxMessage.RTR = CAN_RTR_DATA; //发送的是数据
TxMessage.DLC = 2; //报文数据长度
TxMessage.Data[0] = 0xAB; //报文数据内容
TxMessage.Data[1] = 0xCD;
}
/*
CAN的中断设置
*/
void CAN_NVIC_Configriation(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //选择抢占优先级和响应优先级
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //CAN接收中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //主优先级设置
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级设置
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 通道使能
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{ USART1_Configuration() ; //串口设置
GPIO_Configuration(); //CAN所需GPIO设置
CAN_Mode_Configriation(); //CAN模式参数设置
CAN_NVIC_Configriation(); //CAN中断设置
CAN_Filter_Configriation(); //CAN过滤器设置
printf("\r\n这是一个CAN通讯实验 采用回环测试\r\n") ;
CAN_SETMsg(); //通信所需发送的报文设置
printf("\r\n发送的内容:\r\n") ;
printf("\r\nID号ExtId:0x%x",TxMessage.ExtId) ;
printf("\r\n数据段的内容:DATA[0]=0X%x,DATA[1]=0X%x\r\n",TxMessage.Data[0],TxMessage.Data[1]) ;
CAN_Transmit(CAN1,&TxMessage);
while(flag==0xff); //判断是否发送成功
printf("\r\n成功接受到数据!\r\n") ;
printf("\r\n接受到的内容:\r\n") ;
printf("\r\nID号ExtId:0x%x",RxMessage.ExtId) ;
printf("\r\n数据段的内容:DATA[0]=0X%x,DATA[1]=0X%x\r\n",RxMessage.Data[0],RxMessage.Data[1]) ;
while(1);
}
/*
CAN接收中断函数
*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{ CAN_Receive(CAN1,CAN_FIFO0,&RxMessage); //将接收到的ID、数据等移入到RxMessage结构体中
if((RxMessage.ExtId==0x1225)&&(RxMessage.IDE==CAN_ID_EXT)&&(RxMessage.DLC==2)&&((RxMessage.Data[1]|RxMessage.Data[0]<<8)==0xABCD))
{flag=0; //判断是否接收到发送的数据信息
}
else flag=0xff;
}