#include <sys/ioctl.h>
#include <assert.h>
#include <mqueue.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include "ite/itp.h"
#include "project.h"
#include "scene.h"
#define RX_CAN0_PIN 27
#define TX_CAN0_PIN 28
CAN_HANDLE *can0;
static volatile bool extQuit;
static mqd_t uiMsgQueue = -1; //UI更新消息队列
static mqd_t ctrlMsgQueue = -1; //下发控制器消息队列
static sem_t sem;
CAN_FILTEROBJ FilterTable[16] = { { true, 0x0, 0x1FFFFFFF, false, false },//FILTER0
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER1
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER2
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER3
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER4
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER5
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER6
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER7
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER8
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER9
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER10
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER11
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER12
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER13
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER14
{ false, 0x0, 0x1FFFFFFF, false, false },//FILTER15
};
// 接收CAN消息回调
static void CanRxCallback(void *arg1, uint32_t arg2)
{
sem_post(&sem);
}
// 解析CAN帧
static EBike_Frame ParseFrameData(CAN_RXOBJ _rxObj)
{
EBike_Frame frame;
frame.Union_FrameId.frameId = _rxObj.Identifier;
frame.dataLen = _rxObj.Control.DLC;
memset(frame.data, 0, DLC_MAX);
memcpy(frame.data, _rxObj.RXData, frame.dataLen);
return frame;
}
// 创建CAN接收任务
static void* CanRecvHandle(void* arg)
{
CAN_RXOBJ _rxObj;
while (!extQuit)
{
sem_wait(&sem);
if (ithCANRead(can0, &_rxObj) == 0)
{
printf("can0 ID[%x]: IDE = %x,DLC = %x, RTR = %x,RTS[0] = %x\n"
, _rxObj.Identifier, _rxObj.Control.IDE, _rxObj.Control.DLC, _rxObj.Control.RTR, _rxObj.RXRTS[0]);
printf("data[0-7]=%x %x %x %x %x %x %x %x\n", _rxObj.RXData[0], _rxObj.RXData[1], _rxObj.RXData[2], _rxObj.RXData[3]
, _rxObj.RXData[4], _rxObj.RXData[5], _rxObj.RXData[6], _rxObj.RXData[7]);
// 获取Can帧
EBike_Frame frame = ParseFrameData(_rxObj);
if (GetUpdateStatus() == true)
{
// 用于升级
if (frame.Union_FrameId.msgTypeId == 0x05)
{
// 将数据推送到UI
ExternalEvent evIn;
memset(evIn.buf1, 0, EXTERNAL_BUFFER_SIZE);
memcpy(evIn.buf1, &frame, sizeof(frame));
SendUiMsgQueueInfo(&evIn);
}
}
else
{
// 将数据推送到UI
ExternalEvent evIn;
memset(evIn.buf1, 0, EXTERNAL_BUFFER_SIZE);
memcpy(evIn.buf1, &frame, sizeof(frame));
SendUiMsgQueueInfo(&evIn);
}
}
}
ithCANClose(can0);
free(can0);
sem_destroy(&sem);
return NULL;
}
static void* CanSendHandle(void* arg)
{
CAN_TXOBJ _txObj;
_txObj.Control.RTR = 0x0;
_txObj.Control.IDE = 0x1; // 扩展帧
_txObj.TBSEL = 0x0;
_txObj.SingleShot = 0x0;
_txObj.TTSENSEL = 0x0;
while (!extQuit)
{
ExternalEvent evIn;
int flag = GetCtrlMsgQueueInfo(&evIn);
// 获取消息失败
if (!flag)
{
continue;
}
EBike_Frame *frame = (EBike_Frame*)evIn.buf1;
_txObj.Identifier = frame->Union_FrameId.frameId;
_txObj.Control.DLC = frame->dataLen;
/*printf("_______FrameId: %x, Len: %d, Data: %x %x %x %x %x %x %x %x\n", frame->Union_FrameId.frameId, frame->dataLen, frame->data[0],
frame->data[1], frame->data[2], frame->data[3], frame->data[4], frame->data[5], frame->data[6], frame->data[7]);*/
// 通过Can发送命令给控制器或者更新UI
if (ithCANWrite(can0, &_txObj, frame->data))
{
printf("can0 write fail, bus busy\n");
}
}
ithCANClose(can0);
free(can0);
return NULL;
}
// 创建CAN对象
static void CreateCAN0()
{
ithCANSetGPIO(0, RX_CAN0_PIN, TX_CAN0_PIN);
can0 = (CAN_HANDLE *)malloc(sizeof(CAN_HANDLE));
can0->Instance = 0;
can0->ADDR = CAN0_BASE_ADDRESS;
can0->BaudRate = CAN_250K_1M;
can0->SourceClock = CAN_SRCCLK_60M;
can0->ProtocolType = protocol_CAN_2_0B;
can0->ExternalLoopBackMode = false;
can0->InternalLoopBackMode = false;
can0->ListenOnlyMode = false;
can0->TPtr = FilterTable;
ithCANOpen(can0, (void *)CanRxCallback, (void *)NULL);
}
// 接收到CAN消息,发送消息到Ui消息队列
int SendUiMsgQueueInfo(ExternalEvent* ev)
{
assert(ev);
return mq_send(uiMsgQueue, (char*)ev, sizeof(ExternalEvent), 0);
}
//主线程里循环获取UI队列信息
int GetUiMsgQueueInfo(ExternalEvent *ev)
{
assert(ev);
if (mq_receive(uiMsgQueue, (char*)ev, sizeof(ExternalEvent), 0) > 0)
return 1;
return 0;
}
// 按键下发CAN命令,发送消息到控制器消息队列
int SendCtrlMsgQueueInfo(ExternalEvent* ev)
{
assert(ev);
return mq_send(ctrlMsgQueue, (char*)ev, sizeof(ExternalEvent), 0);
}
// CAN消息写处理线程里循环获取控制器队列信息
int GetCtrlMsgQueueInfo(ExternalEvent *ev)
{
assert(ev);
if (mq_receive(ctrlMsgQueue, (char*)ev, sizeof(ExternalEvent), 0) > 0)
return 1;
return 0;
}
// 外部消息处理初始化
void ExternalInit()
{
// 创建消息队列
struct mq_attr qattr;
qattr.mq_flags = 0;
qattr.mq_maxmsg = 8;
qattr.mq_msgsize = sizeof(ExternalEvent);
uiMsgQueue = mq_open("UI_MsgQueue", O_CREAT | O_NONBLOCK, 0644, &qattr);
assert(uiMsgQueue != -1);
ctrlMsgQueue = mq_open("Ctrl_MsgQueue", O_CREAT | O_NONBLOCK, 0644, &qattr);
assert(ctrlMsgQueue != -1);
// 初始化信号量
sem_init(&sem, 0, 0);
// 创建Can通信对象
CreateCAN0();
pthread_attr_t attr;
static pthread_t MsgRecvTaskId;
static pthread_t MsgSendTaskId;
extQuit = false;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&MsgRecvTaskId, &attr, CanRecvHandle, NULL); // 创建CAN接收任务
pthread_create(&MsgSendTaskId, &attr, CanSendHandle, NULL); // 创建CAN发送任务
}
// 发送CAN命令到控制器
void SendCmdToCtrl(EBike_Frame* frame)
{
ExternalEvent evIn;
memset(evIn.buf1, 0, EXTERNAL_BUFFER_SIZE);
memcpy(evIn.buf1, frame, sizeof(EBike_Frame));
SendCtrlMsgQueueInfo(&evIn);
}
void ExternalExit(void)
{
extQuit = true;
}
CAN通信和信号量示例
最新推荐文章于 2024-07-27 17:29:44 发布