This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
论坛里前辈们的程序见最后,但是有几个问题不懂,请教大家:
1、 FPUEnable();
FPULazyStackingEnable();
FPU的这两句有什么作用?我屏蔽掉也照样可以工作
2、如果想配置为正常模式,不是LOOPBACK模式,是不是应该把寄存器配置的这两句
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;
修改为:
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_BASIC;
看手册还看到说需要把CANIF1CRQ 的BUSY位置1,不知道我理解的对不对?
3、如果我想同时使能CAN0和CAN1,用两个开发板进行通信,一个板子CAN0作为发送,CAN1作为接收,另一个板子相反,是不是同时初始化两个CAN口,就能做这个实验呢?
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "driverlib/can.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "utils/uartstdio.h"
#include "driverlib/rom.h"
// 记录所发送的数据包数
volatile uint32_t g_ulMsgCount_TX = 0;
// 记录所接收的数据包数
volatile uint32_t g_ulMsgCount_RX = 0;
// 用于指示在传输过程中是否出现错误以及错误类型
volatile uint32_t g_bErrFlag = 0;
// 是否接收到数据包标志位
volatile uint32_t g_bRXFlag = 0;
unsigned int INT_CNT_ST = 0; // 发送中断计数器
unsigned int INT_CNT_RE = 0; // 接收中断计数器
unsigned int DATA_LOST = 0; // 接收数据丢失标志位
// 延时1s的函数
void
SimpleDelay(void)
{
SysCtlDelay(16000000 / 3); // delay 1s
}
// CAN中断函数
void CANIntHandler(void)
{
uint32_t ulStatus;
// 通过CANIntStatus函数读取中断的状态
ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
// 如果是控制器状态中断,则说明出现了某种错误
if(ulStatus == CAN_INT_INTID_STATUS)
{
//读取CAN模块所处的状态,并自动清除中断
ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
// 将g_bErrFlag置1,表示有错误发生
g_bErrFlag = 1;
}
else if(ulStatus == 1)
{
INT_CNT_ST++;
// 数据包发送已经完成,清除中断
CANIntClear(CAN0_BASE, 1);
//发送完一个数据包,计数器g_ulMsgCount_TX增加
g_ulMsgCount_TX++;
// 发送已经完成,清除所有的错误信息
g_bErrFlag = 0;
}
else if(ulStatus==2)
{
INT_CNT_RE++;
// 数据包接收已经完成,清除中断
CANIntClear(CAN0_BASE, 2);
// 接收完一个数据包,计数器g_ulMsgCount_RX增加
g_ulMsgCount_RX++;
// 设置Flag说明接收到的数据包正在等待处理,标志位置位
g_bRXFlag = 1;
// 发送已经完成,清除所有的错误信息
g_bErrFlag = 0;
}
}
// 配置CAN模块,循环发送CAN格式数据包并通过LOOPBACK模式接收
// 运行过程中的信息通过UART向计算机机传输
int main(void)
{
// FPUEnable(); //使能FPU
// FPULazyStackingEnable();
// 定义CAN的发送和接收对象
tCANMsgObject sCANMessage;
tCANMsgObject srCANMessage;
// 定义发送数据存储区和接收数据存储区
// unsigned int uIdx; // 循环显示变量
uint32_t ui32SysClock;
uint8_t ucMsgData[4];
uint8_t ucrMsgData[8];
// uint8_t Datareceive[8];
// 禁用中断,在进行中断配置时要保证中断没被使用
IntMasterDisable();
// 设置系统时钟
ui32SysClock = SysCtlClockFreqSet ( ( SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
// CAN0使用PA引脚,使能GPION对应的时钟
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// 使能CAN0模块的时钟信号
SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
//将PA0和PA1两个引脚的功能选择为执行CAN0模块的功能
GPIOPinConfigure(GPIO_PA0_CAN0RX);
GPIOPinConfigure(GPIO_PA1_CAN0TX);
// 对PA0和PA1两个引脚做有关CAN功能的配置
GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// CAN控制器的初始化
CANInit(CAN0_BASE);
// 利用CANBitRateSet函数将CAN的传输速率设置为1MHz
CANBitRateSet(CAN0_BASE, ui32SysClock, 1000000);
// 寄存器操作,将CAN0模块配置为运行于LOOPBACK模式,直接操作寄存器
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;
// 使能CAN0模块
CANEnable(CAN0_BASE);
// 使能CAN0模块的中断
IntEnable(INT_CAN0);
//设置可以引起CAN中断的中断源
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
//初始化配置message object,即待发送的报文
//配置好报文对象后调用CANMessageSet函数进行设置,报文就可以自动被发送出去
*(uint32_t *)ucMsgData = 0; // 配置发送的数据为0
sCANMessage.ui32MsgID = 1; // 使用1作为发送ID
sCANMessage.ui32MsgIDMask = 0; // 不设置MASK屏蔽
sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; //使能发送中断
sCANMessage.ui32MsgLen = sizeof(ucMsgData); //发送数据包大小为4个字节
sCANMessage.pui8MsgData = ucMsgData; // 指向发送数据的指针
// 初始化接收报文,可以接收任何ID的报文对象
srCANMessage.ui32MsgID = 0; // 接收ID位为0
srCANMessage.ui32MsgIDMask = 0; // 不设屏蔽,接收所有东西
srCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; // 使能接收中断和ID过滤
srCANMessage.ui32MsgLen = 8; // 允许最多8个字节的数据
ROM_CANMessageSet(CAN0_BASE, 2 , &srCANMessage, MSG_OBJ_TYPE_RX); // 将message object 2设置为接收报文对象
IntMasterEnable(); // 使能中断
// 发送报文循环,设置每秒发送一个数据包
while(1)
{
CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX); //将待发送的报文配置到message object 1中进行发送中断
SimpleDelay(); // 等待1s,过1s后中断已经执行完了
if(g_bErrFlag) // 通过g_bErrFlag变量查看是否出错
{
g_bErrFlag = 1; // 再次置个1吧
}
else
{
// 如果没有出错,则记录已经发送的报文数目
g_ulMsgCount_TX = g_ulMsgCount_TX; // 做一次重复记载
}
(*(uint32_t *)ucMsgData)++; // 每次发送完毕,都将报文中的数据加1
// 接收报文程序,通过g_bRXFlag判断是否有已经接收到是数据包
if (g_bRXFlag)
{
// 建立指向报文数据的缓存区
srCANMessage.pui8MsgData = ucrMsgData;
CANMessageGet(CAN0_BASE, 2 , &srCANMessage,0); // 将message object2 中的信息读取到srCANMessage接收对象中
g_bRXFlag=0; // 方便下一次接收中断后的处理
if(srCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) // 如果出现数据丢失等错误,标志位提示
{
DATA_LOST = 1;
}
/*
// 输出报文中的数据内容,没什么用了
for(uIdx=0; uIdx<srCANMessage.ui32MsgLen; uIdx++)
{
Datareceive[uIdx] = ucrMsgData[uIdx]; // 再次赋值给一个新的数组
}
// 输出所有已收到的报文数目
g_ulMsgCount_RX = g_ulMsgCount_RX;
*/
}
}
}
guang xiao 说:论坛里前辈们的程序见最后,但是有几个问题不懂,请教大家:
1、 FPUEnable();
FPULazyStackingEnable();
FPU的这两句有什么作用?我屏蔽掉也照样可以工作
这个代码只是使能M4F内核浮点运算单元,不使能当然可以工作,只是做部分算法效率没那么高。
2、如果想配置为正常模式,不是LOOPBACK模式,是不是应该把寄存器配置的这两句
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;修改为:
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_BASIC;看手册还看到说需要把CANIF1CRQ 的BUSY位置1,不知道我理解的对不对?
3、如果我想同时使能CAN0和CAN1,用两个开发板进行通信,一个板子CAN0作为发送,CAN1作为接收,另一个板子相反,是不是同时初始化两个CAN口,就能做这个实验呢?
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "driverlib/can.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "utils/uartstdio.h"
#include "driverlib/rom.h"// 记录所发送的数据包数
volatile uint32_t g_ulMsgCount_TX = 0;
// 记录所接收的数据包数
volatile uint32_t g_ulMsgCount_RX = 0;
// 用于指示在传输过程中是否出现错误以及错误类型
volatile uint32_t g_bErrFlag = 0;
// 是否接收到数据包标志位
volatile uint32_t g_bRXFlag = 0;
unsigned int INT_CNT_ST = 0; // 发送中断计数器
unsigned int INT_CNT_RE = 0; // 接收中断计数器
unsigned int DATA_LOST = 0; // 接收数据丢失标志位// 延时1s的函数
void
SimpleDelay(void)
{SysCtlDelay(16000000 / 3); // delay 1s
}// CAN中断函数
void CANIntHandler(void)
{
uint32_t ulStatus;
// 通过CANIntStatus函数读取中断的状态
ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
// 如果是控制器状态中断,则说明出现了某种错误
if(ulStatus == CAN_INT_INTID_STATUS)
{
//读取CAN模块所处的状态,并自动清除中断
ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
// 将g_bErrFlag置1,表示有错误发生
g_bErrFlag = 1;
}
else if(ulStatus == 1)
{
INT_CNT_ST++;
// 数据包发送已经完成,清除中断
CANIntClear(CAN0_BASE, 1);
//发送完一个数据包,计数器g_ulMsgCount_TX增加
g_ulMsgCount_TX++;
// 发送已经完成,清除所有的错误信息
g_bErrFlag = 0;
}
else if(ulStatus==2)
{
INT_CNT_RE++;
// 数据包接收已经完成,清除中断
CANIntClear(CAN0_BASE, 2);
// 接收完一个数据包,计数器g_ulMsgCount_RX增加
g_ulMsgCount_RX++;
// 设置Flag说明接收到的数据包正在等待处理,标志位置位
g_bRXFlag = 1;
// 发送已经完成,清除所有的错误信息
g_bErrFlag = 0;
}
}// 配置CAN模块,循环发送CAN格式数据包并通过LOOPBACK模式接收
// 运行过程中的信息通过UART向计算机机传输
int main(void)
{// FPUEnable(); //使能FPU
// FPULazyStackingEnable();
// 定义CAN的发送和接收对象
tCANMsgObject sCANMessage;
tCANMsgObject srCANMessage;// 定义发送数据存储区和接收数据存储区
// unsigned int uIdx; // 循环显示变量
uint32_t ui32SysClock;
uint8_t ucMsgData[4];
uint8_t ucrMsgData[8];
// uint8_t Datareceive[8];// 禁用中断,在进行中断配置时要保证中断没被使用
IntMasterDisable();
// 设置系统时钟
ui32SysClock = SysCtlClockFreqSet ( ( SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);// CAN0使用PA引脚,使能GPION对应的时钟
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// 使能CAN0模块的时钟信号
SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
//将PA0和PA1两个引脚的功能选择为执行CAN0模块的功能
GPIOPinConfigure(GPIO_PA0_CAN0RX);
GPIOPinConfigure(GPIO_PA1_CAN0TX);
// 对PA0和PA1两个引脚做有关CAN功能的配置
GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// CAN控制器的初始化
CANInit(CAN0_BASE);
// 利用CANBitRateSet函数将CAN的传输速率设置为1MHz
CANBitRateSet(CAN0_BASE, ui32SysClock, 1000000);// 寄存器操作,将CAN0模块配置为运行于LOOPBACK模式,直接操作寄存器
HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;
// 使能CAN0模块
CANEnable(CAN0_BASE);// 使能CAN0模块的中断
IntEnable(INT_CAN0);//设置可以引起CAN中断的中断源
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);//初始化配置message object,即待发送的报文
//配置好报文对象后调用CANMessageSet函数进行设置,报文就可以自动被发送出去*(uint32_t *)ucMsgData = 0; // 配置发送的数据为0
sCANMessage.ui32MsgID = 1; // 使用1作为发送ID
sCANMessage.ui32MsgIDMask = 0; // 不设置MASK屏蔽
sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; //使能发送中断
sCANMessage.ui32MsgLen = sizeof(ucMsgData); //发送数据包大小为4个字节
sCANMessage.pui8MsgData = ucMsgData; // 指向发送数据的指针// 初始化接收报文,可以接收任何ID的报文对象
srCANMessage.ui32MsgID = 0; // 接收ID位为0
srCANMessage.ui32MsgIDMask = 0; // 不设屏蔽,接收所有东西
srCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; // 使能接收中断和ID过滤
srCANMessage.ui32MsgLen = 8; // 允许最多8个字节的数据
ROM_CANMessageSet(CAN0_BASE, 2 , &srCANMessage, MSG_OBJ_TYPE_RX); // 将message object 2设置为接收报文对象
IntMasterEnable(); // 使能中断// 发送报文循环,设置每秒发送一个数据包
while(1)
{CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX); //将待发送的报文配置到message object 1中进行发送中断
SimpleDelay(); // 等待1s,过1s后中断已经执行完了
if(g_bErrFlag) // 通过g_bErrFlag变量查看是否出错
{
g_bErrFlag = 1; // 再次置个1吧
}
else
{
// 如果没有出错,则记录已经发送的报文数目
g_ulMsgCount_TX = g_ulMsgCount_TX; // 做一次重复记载
}
(*(uint32_t *)ucMsgData)++; // 每次发送完毕,都将报文中的数据加1
// 接收报文程序,通过g_bRXFlag判断是否有已经接收到是数据包
if (g_bRXFlag)
{
// 建立指向报文数据的缓存区
srCANMessage.pui8MsgData = ucrMsgData;
CANMessageGet(CAN0_BASE, 2 , &srCANMessage,0); // 将message object2 中的信息读取到srCANMessage接收对象中
g_bRXFlag=0; // 方便下一次接收中断后的处理if(srCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) // 如果出现数据丢失等错误,标志位提示
{
DATA_LOST = 1;
}
/*
// 输出报文中的数据内容,没什么用了
for(uIdx=0; uIdx<srCANMessage.ui32MsgLen; uIdx++)
{
Datareceive[uIdx] = ucrMsgData[uIdx]; // 再次赋值给一个新的数组
}
// 输出所有已收到的报文数目
g_ulMsgCount_RX = g_ulMsgCount_RX;
*/
}
}
}
其它问题我需要研究一下再回复
您好,请教您个问题。目前我使用CAN0同时作为发送和接收处理,接收设置为:可以接收总线上的所有CAN信息,发送目前是只发送ID为1的数据,但是我想实现这样的功能:不管接收到的总线上CAN信息的帧ID是多少,发送的ID能够根据帧ID的不同来发送数据,那么在程序中对不同设置的帧ID接收如何做处理?
谢谢您!