专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
求stm32 can 程序
2019-10-12 14:25
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
14941
49
1667
本人之前购买ALIENTEK MINISTM32 103RBT6发现没有can程序,因学习需要 请求各位大侠 不吝赐教一份can程序,不胜感激~~
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
49条回答
正点原子
2019-10-14 23:39
#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
//回环模式初始化
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 CAN_LoopBack_Init(void)
{
u16 i=0;
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X000B8000;//PA11 RX,PA12 TX推挽输出
GPIOA->ODR|=3<<11;
RCC->APB1ENR|=1<<25;//使能CAN时钟 CAN使用的是APB1的时钟(max:36M)
CAN->MCR=0x0000; //退出睡眠模式(同时设置所有位为0)
CAN->MCR|=1<<0; //请求CAN进入初始化模式
while((CAN->MSR&1<<0)==0)
{
i++;
if(i>100)return 1;//进入初始化模式失败
}
CAN->MCR|=0<<7; //非时间触发通信模式
CAN->MCR|=0<<6; //软件自动离线管理
CAN->MCR|=0<<5; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN->MCR|=1<<4; //禁止报文自动传送
CAN->MCR|=0<<3; //报文不锁定,新的覆盖旧的
CAN->MCR|=0<<2; //优先级由报文标识符决定
CAN->BTR=0x00000000;//清除原来的设置.
CAN->BTR|=1<<30; //环回模式
CAN->BTR|=0<<24; //重新同步跳跃宽度(Tsjw)为1个时间单位
CAN->BTR|=6<<20; //Tbs2=7个时间单位
CAN->BTR|=7<<16; //Tbs1=8个时间单位
CAN->BTR|=4<<0; //分频系数(Fdiv)为5
//波特率:Fpclk1/((Tsjw+Tbs1+Tbs2)*Fdiv),如上设置为 36M/((1+8+7)*5)=450Kbps
CAN->MCR&=~(1<<0); //请求CAN退出初始化模式
while((CAN->MSR&1<<0)==1)
{
i++;
if(i>0XFFF0)return 2;//退出初始化模式失败
}
//过滤器初始化
CAN->FMR|=1<<0; //过滤器组工作在初始化模式
CAN->FA1R&=~(1<<0); //过滤器0不激活
CAN->FS1R|=1<<0; //过滤器位宽为32位.
CAN->FM1R|=0<<0; //过滤器0工作在标识符屏蔽位模式
CAN->FFA1R|=0<<0; //过滤器0关联到FIFO0
CAN->sFilterRegister[0].FR1=0X00000000;//32位ID
CAN->sFilterRegister[0].FR2=0X00000000;//32位MASK
CAN->FA1R|=1<<0; //激活过滤器0
CAN->FMR&=0<<0; //过滤器组进入正常模式
return 0;
}
//id:标准ID(11位)/扩展ID(11位+18位)
//ide:0,标准帧;1,扩展帧
//rtr:0,数据帧;1,远程帧
//len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
//*dat:数据指针.
//返回值:0~3,邮箱编号.0XFF,无有效邮箱.
u8 Can_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat)
{
u8 mbox;
if(CAN->TSR&(1<<26))mbox=0; //邮箱0为空
else if(CAN->TSR&(1<<27))mbox=1; //邮箱1为空
else if(CAN->TSR&(1<<28))mbox=2; //邮箱2为空
else return 0XFF;//无空邮箱,无法发送
CAN->sTxMailBox[mbox].TIR&=~(1<<0); //发送数据请求 无效
if(ide==0) //标准帧
{
id&=0x7ff;//取低11位stdid
id<<=21;
CAN->sTxMailBox[mbox].TIR&=~0XFFE00000;
}else //扩展帧
{
id&=0X1FFFFFFF;//取低32位extid
id<<=3;
CAN->sTxMailBox[mbox].TIR&=~0X00000007;
}
CAN->sTxMailBox[mbox].TIR|=id;
CAN->sTxMailBox[mbox].TIR&=~(1<<2);
CAN->sTxMailBox[mbox].TIR|=ide<<2;
CAN->sTxMailBox[mbox].TIR&=~(1<<1);
CAN->sTxMailBox[mbox].TIR|=rtr<<1;
len&=0X0F;//得到低四位
CAN->sTxMailBox[mbox].TDTR&=~(0X0000000F);
CAN->sTxMailBox[mbox].TDTR|=len; //设置DLC.
//待发送数据存入邮箱.
CAN->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
((u32)dat[6]<<16)|
((u32)dat[5]<<8)|
((u32)dat[4]));
CAN->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
((u32)dat[2]<<16)|
((u32)dat[1]<<8)|
((u32)dat[0]));
CAN->sTxMailBox[mbox].TIR|=1<<0; //请求发送邮箱数据
return mbox;
}
//获得发送状态.
//mbox:邮箱编号;
//返回值:发送状态. 0,挂起;0X05,发送失败;0X07,发送成功.
u8 Can_Tx_Staus(u8 mbox)
{
u8 sta=0;
switch (mbox)
{
case 0:
sta |= CAN->TSR&(1<<0); //RQCP0
sta |= CAN->TSR&(1<<1); //TXOK0
sta |=((CAN->TSR&(1<<26))>>24); //TME0
break;
case 1:
sta |= CAN->TSR&(1<<8)>>8; //RQCP1
sta |= CAN->TSR&(1<<9)>>8; //TXOK1
sta |=((CAN->TSR&(1<<27))>>25); //TME1
break;
case 2:
sta |= CAN->TSR&(1<<16)>>16; //RQCP2
sta |= CAN->TSR&(1<<17)>>16; //TXOK2
sta |=((CAN->TSR&(1<<28))>>26); //TME2
break;
default:
sta=0X05;//邮箱号不对,肯定失败.
break;
}
return sta;
}
//得到在FIFO0/FIFO1中接收到的报文个数.
//fifox:0/1.FIFO编号;
//返回值:FIFO0/FIFO1中的报文个数.
u8 Can_Msg_Pend(u8 fifox)
{
if(fifox==0)return CAN->RF0R&0x03;
else if(fifox==1)return CAN->RF1R&0x03;
else return 0;
}
//接收数据
void Can_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat)
{
*ide=CAN->sFIFOMailBox[fifox].RIR&0x04;//得到标识符选择位的值
if(*ide==0)//标准标识符
{
*id=CAN->sFIFOMailBox[fifox].RIR>>21;
}else //扩展标识符
{
*id=CAN->sFIFOMailBox[fifox].RIR>>3;
}
*rtr=CAN->sFIFOMailBox[fifox].RIR&0x02; //得到远程发送请求值.
*len=CAN->sFIFOMailBox[fifox].RDTR&0x0F;//得到DLC
//*fmi=(CAN->sFIFOMailBox[FIFONumber].RDTR>>8)&0xFF;//得到FMI
//接收数据
dat[0]=CAN->sFIFOMailBox[fifox].RDLR&0XFF;
dat[1]=(CAN->sFIFOMailBox[fifox].RDLR>>8)&0XFF;
dat[2]=(CAN->sFIFOMailBox[fifox].RDLR>>16)&0XFF;
dat[3]=(CAN->sFIFOMailBox[fifox].RDLR>>24)&0XFF;
dat[4]=CAN->sFIFOMailBox[fifox].RDHR&0XFF;
dat[5]=(CAN->sFIFOMailBox[fifox].RDHR>>8)&0XFF;
dat[6]=(CAN->sFIFOMailBox[fifox].RDHR>>16)&0XFF;
dat[7]=(CAN->sFIFOMailBox[fifox].RDHR>>24)&0XFF;
if(fifox==0)CAN->RF0R|=0X20;//释放FIFO0邮箱
else if(fifox==1)CAN->RF1R|=0X20;//释放FIFO1邮箱
}
void 
ENDINT_TEST(void)
{
u8 i=0;
u8 mbox=0;
u8 txbuf[8]={0XCA,0XFE,0X12,0,0,0,0,0};
u8 rxbuf[8];
u32 id;
u8 ide,rtr,len;
CAN_LoopBack_Init();
mbox=Can_Tx_Msg(0x11,0,0,3,txbuf);
while((Can_Tx_Staus(mbox)!=0X07)&&(i<0XFF))
{
i++;
}
i=0;
while(Can_Msg_Pend(0)<1 && (i<100))
{
i++;
delay_ms(1);
}
Can_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);
printf(" PENDINT_TEST ");
printf("id:%d ",id);
printf("ide:%d ",ide);
printf("rtr:%d ",rtr);
printf("len:%d ",len);
printf("rxbuf[0]:%d ",rxbuf[0]);
printf("rxbuf[1]:%d ",rxbuf[1]);
printf("rxbuf[2]:%d ",rxbuf[2]);
printf("rxbuf[3]:%d ",rxbuf[3]);
printf("rxbuf[4]:%d ",rxbuf[4]);
printf("rxbuf[5]:%d ",rxbuf[5]);
printf("rxbuf[6]:%d ",rxbuf[6]);
printf("rxbuf[7]:%d ",rxbuf[7]);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
u8 rxbuf[8];
u32 id;
u8 ide,rtr,len;
Can_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);
printf("id:%d ",id);
printf("ide:%d ",ide);
printf("rtr:%d ",rtr);
printf("len:%d ",len);
printf("rxbuf[0]:%d ",rxbuf[0]);
printf("rxbuf[1]:%d ",rxbuf[1]);
printf("rxbuf[2]:%d ",rxbuf[2]);
printf("rxbuf[3]:%d ",rxbuf[3]);
printf("rxbuf[4]:%d ",rxbuf[4]);
printf("rxbuf[5]:%d ",rxbuf[5]);
printf("rxbuf[6]:%d ",rxbuf[6]);
printf("rxbuf[7]:%d ",rxbuf[7]);
}
void CANINT_TEST(void)
{
u8 i=0;
u8 mbox=0;
u8 txbuf[8]={0X1A,0X23,0XBF,0,0,0,0,0};
CAN_LoopBack_Init();
CAN->IER|=1<<1;//FIFO0消息挂号中断允许.
MY_NVIC_Init(3,2,USB_LP_CAN_RX0_IRQChannel,2);//组2
printf(" CANINT_TEST ");
mbox=Can_Tx_Msg(0x11,0,0,3,txbuf);
while((Can_Tx_Staus(mbox)!=0X07)&&(i<0XFF))
{
i++;
}
delay_ms(100);
}
加载中...
查看其它49个回答
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#include "led.h"
#include "delay.h"
#include "usart.h"
//回环模式初始化
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 CAN_LoopBack_Init(void)
{
u16 i=0;
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X000B8000;//PA11 RX,PA12 TX推挽输出
GPIOA->ODR|=3<<11;
RCC->APB1ENR|=1<<25;//使能CAN时钟 CAN使用的是APB1的时钟(max:36M)
CAN->MCR=0x0000; //退出睡眠模式(同时设置所有位为0)
CAN->MCR|=1<<0; //请求CAN进入初始化模式
while((CAN->MSR&1<<0)==0)
{
i++;
if(i>100)return 1;//进入初始化模式失败
}
CAN->MCR|=0<<7; //非时间触发通信模式
CAN->MCR|=0<<6; //软件自动离线管理
CAN->MCR|=0<<5; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN->MCR|=1<<4; //禁止报文自动传送
CAN->MCR|=0<<3; //报文不锁定,新的覆盖旧的
CAN->MCR|=0<<2; //优先级由报文标识符决定
CAN->BTR=0x00000000;//清除原来的设置.
CAN->BTR|=1<<30; //环回模式
CAN->BTR|=0<<24; //重新同步跳跃宽度(Tsjw)为1个时间单位
CAN->BTR|=6<<20; //Tbs2=7个时间单位
CAN->BTR|=7<<16; //Tbs1=8个时间单位
CAN->BTR|=4<<0; //分频系数(Fdiv)为5
//波特率:Fpclk1/((Tsjw+Tbs1+Tbs2)*Fdiv),如上设置为 36M/((1+8+7)*5)=450Kbps
CAN->MCR&=~(1<<0); //请求CAN退出初始化模式
while((CAN->MSR&1<<0)==1)
{
i++;
if(i>0XFFF0)return 2;//退出初始化模式失败
}
//过滤器初始化
CAN->FMR|=1<<0; //过滤器组工作在初始化模式
CAN->FA1R&=~(1<<0); //过滤器0不激活
CAN->FS1R|=1<<0; //过滤器位宽为32位.
CAN->FM1R|=0<<0; //过滤器0工作在标识符屏蔽位模式
CAN->FFA1R|=0<<0; //过滤器0关联到FIFO0
CAN->sFilterRegister[0].FR1=0X00000000;//32位ID
CAN->sFilterRegister[0].FR2=0X00000000;//32位MASK
CAN->FA1R|=1<<0; //激活过滤器0
CAN->FMR&=0<<0; //过滤器组进入正常模式
return 0;
}
//id:标准ID(11位)/扩展ID(11位+18位)
//ide:0,标准帧;1,扩展帧
//rtr:0,数据帧;1,远程帧
//len:要发送的数据长度(固定为8个字节,在时间触发模式下,有效数据为6个字节)
//*dat:数据指针.
//返回值:0~3,邮箱编号.0XFF,无有效邮箱.
u8 Can_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat)
{
u8 mbox;
if(CAN->TSR&(1<<26))mbox=0; //邮箱0为空
else if(CAN->TSR&(1<<27))mbox=1; //邮箱1为空
else if(CAN->TSR&(1<<28))mbox=2; //邮箱2为空
else return 0XFF;//无空邮箱,无法发送
CAN->sTxMailBox[mbox].TIR&=~(1<<0); //发送数据请求 无效
if(ide==0) //标准帧
{
id&=0x7ff;//取低11位stdid
id<<=21;
CAN->sTxMailBox[mbox].TIR&=~0XFFE00000;
}else //扩展帧
{
id&=0X1FFFFFFF;//取低32位extid
id<<=3;
CAN->sTxMailBox[mbox].TIR&=~0X00000007;
}
CAN->sTxMailBox[mbox].TIR|=id;
CAN->sTxMailBox[mbox].TIR&=~(1<<2);
CAN->sTxMailBox[mbox].TIR|=ide<<2;
CAN->sTxMailBox[mbox].TIR&=~(1<<1);
CAN->sTxMailBox[mbox].TIR|=rtr<<1;
len&=0X0F;//得到低四位
CAN->sTxMailBox[mbox].TDTR&=~(0X0000000F);
CAN->sTxMailBox[mbox].TDTR|=len; //设置DLC.
//待发送数据存入邮箱.
CAN->sTxMailBox[mbox].TDHR=(((u32)dat[7]<<24)|
((u32)dat[6]<<16)|
((u32)dat[5]<<8)|
((u32)dat[4]));
CAN->sTxMailBox[mbox].TDLR=(((u32)dat[3]<<24)|
((u32)dat[2]<<16)|
((u32)dat[1]<<8)|
((u32)dat[0]));
CAN->sTxMailBox[mbox].TIR|=1<<0; //请求发送邮箱数据
return mbox;
}
//获得发送状态.
//mbox:邮箱编号;
//返回值:发送状态. 0,挂起;0X05,发送失败;0X07,发送成功.
u8 Can_Tx_Staus(u8 mbox)
{
u8 sta=0;
switch (mbox)
{
case 0:
sta |= CAN->TSR&(1<<0); //RQCP0
sta |= CAN->TSR&(1<<1); //TXOK0
sta |=((CAN->TSR&(1<<26))>>24); //TME0
break;
case 1:
sta |= CAN->TSR&(1<<8)>>8; //RQCP1
sta |= CAN->TSR&(1<<9)>>8; //TXOK1
sta |=((CAN->TSR&(1<<27))>>25); //TME1
break;
case 2:
sta |= CAN->TSR&(1<<16)>>16; //RQCP2
sta |= CAN->TSR&(1<<17)>>16; //TXOK2
sta |=((CAN->TSR&(1<<28))>>26); //TME2
break;
default:
sta=0X05;//邮箱号不对,肯定失败.
break;
}
return sta;
}
//得到在FIFO0/FIFO1中接收到的报文个数.
//fifox:0/1.FIFO编号;
//返回值:FIFO0/FIFO1中的报文个数.
u8 Can_Msg_Pend(u8 fifox)
{
if(fifox==0)return CAN->RF0R&0x03;
else if(fifox==1)return CAN->RF1R&0x03;
else return 0;
}
//接收数据
void Can_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat)
{
*ide=CAN->sFIFOMailBox[fifox].RIR&0x04;//得到标识符选择位的值
if(*ide==0)//标准标识符
{
*id=CAN->sFIFOMailBox[fifox].RIR>>21;
}else //扩展标识符
{
*id=CAN->sFIFOMailBox[fifox].RIR>>3;
}
*rtr=CAN->sFIFOMailBox[fifox].RIR&0x02; //得到远程发送请求值.
*len=CAN->sFIFOMailBox[fifox].RDTR&0x0F;//得到DLC
//*fmi=(CAN->sFIFOMailBox[FIFONumber].RDTR>>8)&0xFF;//得到FMI
//接收数据
dat[0]=CAN->sFIFOMailBox[fifox].RDLR&0XFF;
dat[1]=(CAN->sFIFOMailBox[fifox].RDLR>>8)&0XFF;
dat[2]=(CAN->sFIFOMailBox[fifox].RDLR>>16)&0XFF;
dat[3]=(CAN->sFIFOMailBox[fifox].RDLR>>24)&0XFF;
dat[4]=CAN->sFIFOMailBox[fifox].RDHR&0XFF;
dat[5]=(CAN->sFIFOMailBox[fifox].RDHR>>8)&0XFF;
dat[6]=(CAN->sFIFOMailBox[fifox].RDHR>>16)&0XFF;
dat[7]=(CAN->sFIFOMailBox[fifox].RDHR>>24)&0XFF;
if(fifox==0)CAN->RF0R|=0X20;//释放FIFO0邮箱
else if(fifox==1)CAN->RF1R|=0X20;//释放FIFO1邮箱
}
void ENDINT_TEST(void)
{
u8 i=0;
u8 mbox=0;
u8 txbuf[8]={0XCA,0XFE,0X12,0,0,0,0,0};
u8 rxbuf[8];
u32 id;
u8 ide,rtr,len;
CAN_LoopBack_Init();
mbox=Can_Tx_Msg(0x11,0,0,3,txbuf);
while((Can_Tx_Staus(mbox)!=0X07)&&(i<0XFF))
{
i++;
}
i=0;
while(Can_Msg_Pend(0)<1 && (i<100))
{
i++;
delay_ms(1);
}
Can_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);
printf(" PENDINT_TEST ");
printf("id:%d ",id);
printf("ide:%d ",ide);
printf("rtr:%d ",rtr);
printf("len:%d ",len);
printf("rxbuf[0]:%d ",rxbuf[0]);
printf("rxbuf[1]:%d ",rxbuf[1]);
printf("rxbuf[2]:%d ",rxbuf[2]);
printf("rxbuf[3]:%d ",rxbuf[3]);
printf("rxbuf[4]:%d ",rxbuf[4]);
printf("rxbuf[5]:%d ",rxbuf[5]);
printf("rxbuf[6]:%d ",rxbuf[6]);
printf("rxbuf[7]:%d ",rxbuf[7]);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
u8 rxbuf[8];
u32 id;
u8 ide,rtr,len;
Can_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);
printf("id:%d ",id);
printf("ide:%d ",ide);
printf("rtr:%d ",rtr);
printf("len:%d ",len);
printf("rxbuf[0]:%d ",rxbuf[0]);
printf("rxbuf[1]:%d ",rxbuf[1]);
printf("rxbuf[2]:%d ",rxbuf[2]);
printf("rxbuf[3]:%d ",rxbuf[3]);
printf("rxbuf[4]:%d ",rxbuf[4]);
printf("rxbuf[5]:%d ",rxbuf[5]);
printf("rxbuf[6]:%d ",rxbuf[6]);
printf("rxbuf[7]:%d ",rxbuf[7]);
}
void CANINT_TEST(void)
{
u8 i=0;
u8 mbox=0;
u8 txbuf[8]={0X1A,0X23,0XBF,0,0,0,0,0};
CAN_LoopBack_Init();
CAN->IER|=1<<1;//FIFO0消息挂号中断允许.
MY_NVIC_Init(3,2,USB_LP_CAN_RX0_IRQChannel,2);//组2
printf(" CANINT_TEST ");
mbox=Can_Tx_Msg(0x11,0,0,3,txbuf);
while((Can_Tx_Staus(mbox)!=0X07)&&(i<0XFF))
{
i++;
}
delay_ms(100);
}
一周热门 更多>