motorcontroldemo_035/Vsrc/V_CANtoRS.c
2019-07-29 08:17:46 +03:00

328 lines
10 KiB
C

/*!
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_CANtoRS.c
\brief Ïðåîáðàçîâàòåëü ïîñûëîê CAN â RS è îáðàòíî. Ðàáîòàåò
ñîâìåñòíî ñ äðàéâåðîì CANOpen
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 2.0 25/03/2016
\addtogroup v_CANtoRS
@{
*/
#include "DSP.h"
#include "main.h"
//! \memberof TCANtoRS
void CANtoRS_init(TCANtoRS *p) {
GPIOB->ALTFUNCSET = (1 << 8) + (1 << 9);
GPIOB->DENSET = (1 << 8) + (1 << 9);
p->UART=UART1;//Èñïîëüçóåìûé â äðàéâåðå íîìåð UART (0, 1)
p->UART->CR_bit.UARTEN = 1; // Ðàçðåøèòü ðàáîòó UART
// Íàñòðîéêà ÷àñòîòû â äâóõ ðåãèñòðàõ:
// çàäàíèå äåëèòåëÿ ÷àñòîòû äëÿ ïîëó÷åíèÿ BaudRate
// Ò.ê. áëîê UART òàêòèðóåòñÿ ñ ÷àñòîòîé 25 ÌÃö (òàê íàñòðîåíî â èíèòå ìèêðîêîíòðîëëåðà),
// òî äëÿ ïîëó÷åíèÿ ÷àñòîòû 57600 áèò/ñ íåîáõîäèì
// äåëèòåëü 25000000 / (16 * 57600) = 27,126736111111111111111111111111
// Öåëàÿ ÷àñòü I = 27
// Äðîáíàÿ ÷àñòü F = (int)( 0.126736111*64 + 0.5 ) = 8
// Ôîðìóëû ñì. â äîêóìåíòàöèè
p->UART->IBRD_bit.DIVINT= 27;
p->UART->FBRD_bit.DIVFRAC = 8;
p->UART->LCRH_bit.SPS = 0; // Íåò ïðîâåðêè ÷åòíîñòè
p->UART->LCRH_bit.WLEN = 3; // Äëèíà ïîñûëêè 8 áèò
p->UART->LCRH_bit.FEN = 1; // Èñïîëüçîâàòü FIFO
p->UART->CR_bit.TXE = 1; // Ðàçðåøèòü ïðè¸ì
p->UART->CR_bit.RXE = 1; // Ðàçðåøèòü ïåðåäà÷ó
p->UART->LCRH_bit.STP2 = 0; // 1 ñòîï-áèò
p->CounterWrongCRC=0;
p->CounterRes=0;
p->CounterSended=0;
p->PacketInWait=0;
}
//! Èç çàäàííîãî äëÿ ïåðåäà÷è ìàññèâà ôóíêöèÿ ôîðìèðóåò
//!API ïàêåò, à çàòåì âûçûâàåò ôóíêöèþ
//!ïîáàéòîâîé îòïðàâêè
//! \memberof TCANtoRS
Uint16 CANtoRS_SendP(Uint16* Data, int16 len, TCANtoRS *p) {
volatile int16 i;
Uint16 MyCRC;
p->buf_out[0]=0x7E;
for (i=0;i<len;i++)
p->buf_out[i+1]=Data[i];
MyCRC=CANtoRS_C_CRC(p,Data,len);
p->buf_out[len+1]=MyCRC & 0xFF;//ïåðâûé áàéò
p->buf_out[len+2]=(MyCRC>>8) & 0xFF;//âòîðîé áàéò
p->all_len=1+len+2;//ïîëíàÿ äëèíà=ñèãíàòóðà+äàííûå + êîíòðîëüíàÿ ñóììà
i = 0;
// Åñëè áóôåð TX íå çàïîëíåí, òî îòïðàâëÿåì âñå áàéòû èç áóôåðà
while ((p->UART->FR_bit.TXFF != 1) && (i < p->all_len)){
p->UART->DR = p->buf_out[i];
i++;
}
return 1;
}
#define CRC_MAGIC_NUMBER 0xA001
//! Ôóíêöèÿ ñ÷èòàåò êîíòðîëüíóþ ñóììó ïàêåòà
//! è ñðàâíèâàåò ñ ïðèíÿòîé. Åñëè âñå âåðíî, òî âîçâðàùàåò 1
//! \memberof TCANtoRS
Uint16 CANtoRS_C_CRC(TCANtoRS *p,Uint16 *Data,Uint16 len) { //ïðîâåðêà êîíòðîëüíîé ñóììû ïðèíÿòîãî API ïàêåòà
int16 i,j;
Uint16 MyCalcCRC=0xFFFF;
for (j=0;j<len;j++) {
MyCalcCRC=MyCalcCRC^(Data[j++]&0xFF);
for (i=0; i<16; i++)
if (MyCalcCRC&0x01) {
MyCalcCRC=(MyCalcCRC>>1);
MyCalcCRC=MyCalcCRC^CRC_MAGIC_NUMBER;
} else
MyCalcCRC=(MyCalcCRC>>1);
}
return MyCalcCRC;
}
/*! Ôóíêöèÿ âûçûâàåòñÿ, êîãäà ïðèøëè êàêèå-òî äàííûå,
è îáðàáàòûâàåò èõ êàê ïåðåäàííûé CAN ïàêåò. Âûäåëÿåò
èäåíòèôèêàòîð, äëèíó è ïðî÷åå. Ðåç-ò ïîìåùàåò â ñòðóêòóðó
p->MSG */
//! \memberof TCANtoRS
void CANtoRS_Analysis(TCANtoRS *p) {
int16 i,j;
//ïîñûëêà äàííûõ íà÷èíàåòñÿ ñ 12ãî áàéòà,
//äî ýòîãî ñëóæåáíàÿ èíôîðìàöèÿ API ïàêåòà
p->MSG.id=0;
p->MSG.id=(p->ReadPackData[0] & 7)<<8; //íèæíèå 3 áèòà ñäâèãàåì íàâåðõ;
p->MSG.id|=p->ReadPackData[1];
p->MSG.dlc=(p->ReadPackData[0]>>4) & 0xF; //âåðõíèå 4 áèòà ñäâèãàåì âíèç; äëèíà ïîñûëêè
for (i=2,j=0;i<CANTORS_READ_DATA_MAX_LEN;i++,j++)
p->MSG.data[j]=p->ReadPackData[i];
p->callback_go=1;
}
/*! Ïîáàéòîâûé îáðàáîò÷èê ïðèõîäÿùèõ ïî SCI äàííûõ.
Ðàáîòàåò ïî ïðèíöèïó äèñêðåòíîãî àâòîìàòà è ïûòàåòñÿ
íàéòè â ïîñûëêå API ïàêåò. Ñíà÷àëà æäåò çàäàííóþ ñèãíàòóðó,
ïîòîì äëèíó è ò.ï. Â êîíöå ïðîâåðÿåò êîíòðîëüíóþ ñóììó è
âûçûâàåò äàëüíåéøèå îáðàáîò÷èêè */
//! \memberof TCANtoRS
void CANtoRS_Receive(TCANtoRS *p) {
Uint16 MyReadCRC_u16;
Uint16 MyCalcCRC;
Uint32 temp_byte;
Uint16 repeat;
for (repeat=0;repeat<7; repeat++) {//îáðàáîòêà íå áîëåå n áàéò çà îäèí âõîä â ôóíêöèþ
switch (p->APIpacketMode) {
case 0: { //îæèäàíèå ñèãíàòóðû
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
if (temp_byte!=0x7e) {
p->MessDrop3++;
return;
}
p->ReadPackDataCounter=0;//ñ÷åò÷èê äàííûõ
p->APIpacketMode=1; //ñèãðíàòóðà íàéäåíà, ðåæèì ïðèåìà äàííûõ
break;
};
case 1: { //îæèäàíèå äàííûõ(ïîëåçíàÿ íàãðóçêà) ïàêåòà
//âñå ïîñëåäóþùèå áàéòû ñêëàäûâàåì â API áóôåð
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
p->ReadPackData[p->ReadPackDataCounter++]=temp_byte;
if (p->ReadPackDataCounter>=CANTORS_READ_DATA_MAX_LEN) {
p->ReadPackDataCounter=0;//ñ÷åò÷èê äàííûõ
p->ReadCRCCounter=0;//ñ÷åò÷èê êîíòðîëüíîé ñóììû
p->APIpacketMode=2; //äàííûå ïðèíÿòû, ðåæèì ïðèåìà è ïðîâåðñè CRC
}
break;
};
case 2: { //îæèäàíèå CRC
//âñå ïîñëåäóþùèå áàéòû ñêëàäûâàåì â CRC áóôåð
if (p->UART->FR_bit.RXFE)
return;
temp_byte = p->UART->DR_bit.DATA;
p->ReadCRC[p->ReadCRCCounter++]=temp_byte;
if (p->ReadCRCCounter>=2) {
p->ReadCRCCounter=0;//ñ÷åò÷èê êîíòðîëüíîé ñóììû
MyReadCRC_u16=(p->ReadCRC[0]&0xFF)+((p->ReadCRC[1]<<8)&0xFF00);//çàïàêîâûâàåì äâóõáàéòîâóþ CRC â îäíó ïåðåìåííóþ
MyCalcCRC=CANtoRS_C_CRC(p,p->ReadPackData,CANTORS_READ_DATA_MAX_LEN);
if (MyCalcCRC!=MyReadCRC_u16) {
//îøèáêà!
p->CounterWrongCRC++;
p->APIpacketMode=0;
break;
}//êîíòðîëüíàÿ ñóììà ïðèíÿòà è âåðíà
CANtoRS_Analysis(p);
if (p->callback_go) { //åñëè âûñòàâëåí ôëàã, âûçîâ callback
p->callback_go=0;
p->APIpacketMode=3; //îáðàáîòêà callback
}
else
p->APIpacketMode=0;
return;
}
break;
};
case 3: { //îáðàáîòêà callback
p->CounterRes++;
p->callback(&co1_vars, &(p->MSG));
p->APIpacketMode=0;
break;
};
default:
return;
}
}
return;
}
/*! Äîëæíà âûçûâàòüñÿ êàæäóþ ñåêóíäó è îòñûëàåò
CAN ïàêåòû HeartBeat. Åñëè îòîñëàòü íå âûõîäèò (ïåðåäà÷à çàíÿòà),
òî ñîêðàùàåò ïîñëåäóþùèé òàéìàóò è, íåìíîãî îáîæäàâ, ïûòàåòñÿ
îòïðàâèòü çàíîâî */
//! \memberof TCANtoRS
void CANtoRS_HeartBeat(TCANtoRS *p) {
TZCanMsg MSG;
int16 i;
MSG.id=0xE<<7;//heartbeat
MSG.id|=*p->nodeID;//íîìåð óçëà
MSG.dlc=1;//äëèíà
for (i=0;i<8;MSG.data[i++]=0);//î÷èñòêà
MSG.data[0]=5;//äàííûå heartbeat
if (!CANtoRS_Write(&MSG,p)) { //åñëè íå ïîëó÷èëîñü îòïðàâèòü
p->HeartCounter=(CANTORS_HEART_COUNTER_MAX-3); //âñêîðå ïðîáóåì ñäåëàòü ýòî åùå ðàç
p->HeartBeatGo=1;//è åñëè áóäåò ñîáûòèå íà îòïðàâêó SDO, íî áóäåò çíàòü, ÷òî íàäî ïðîïóñòèòü
} else {
p->HeartBeatGo=0;
}
}
//! \memberof TCANtoRS
Uint16 CANtoRS_WriteHelper(TZCanMsg* MSG,TCANtoRS *p) {
if (p->HeartBeatGo) { //õî÷åò îòïðàâèòüñÿ HeartBeat
CANtoRS_HeartBeat(p);
p->MessDrop1++;
return 0;//ñîîáùåíèå òåðÿåì...
}
if (CANtoRS_Write(MSG,p))
p->CounterSended++;
else {
p->MessDrop2++;
return 0;
}
return 1;
}
/*! Èç ñòðóêòóðû CAN ïàêåòà ôîðìèðóåò ìàññèâ-ïîñûëêó,
ãäå âíà÷àëå 4 áèòà - äëèíà, ïîòîì 1 áèò ïðîïóñê è 11 èäåíòèôèêàòîð.
Äàëåå íåïîñðåäñòâåííî äàííûå. Ïîñëå êîíñòðóèðîâàíèÿ ïîñûëêà îòïðàâëÿåòñÿ*/
//! \memberof TCANtoRS
Uint16 CANtoRS_Write(TZCanMsg* MSG,TCANtoRS *p) {
if (!p->PacketInWait) { //íåò ïàêåòà â áóôåðå
//êîïèðóåì âî âðåìåííûé áóôåð
p->bufMSG=*MSG;
p->PacketInWait=1;//ôëàã, ÷òî â áóôåðå ÷òî-òî åñòü
return 1;
//ñ÷èòàåòñÿ, ÷òî áóôåðà íà 1 ïîçèöèþ äîëæíî õâàòàòü
} else
return 0;
}
//! \memberof TCANtoRS
Uint16 CANtoRS_Write_Real(TZCanMsg* MSG,TCANtoRS *p) {
int16 i;
p->TempData[0]=(MSG->dlc & 0xF)<<4;
p->TempData[0]|=(MSG->id >> 8) & 7;
p->TempData[1]=MSG->id & 0xFF;
for (i=0;i<8;i++) p->TempData[i+2]=MSG->data[i];
CANtoRS_SendP(p->TempData,10,p);
return 1;
}
/*! Âûçûâàåòñÿ èç ìèëëèñåêóíäíîãî òàéìåðà, îòñ÷èòûâàåò 1 ñåêóíäó
è âûçûâàåò ôóíêöèþ îòïðàâêè HeartBeat. Çàîäíî ïðîâåðÿåò,
åñëè â SCI âîçíèêëà êàêàÿ-òî îøèáêà è îí îñòàíîâèëñÿ, ïåðåçàïóñêàåò.
*/
//! \memberof TCANtoRS
void CANtoRS_calc(TCANtoRS *p) {
//åñëè â áóôåðå åñòü ïàêåò, îæèäàþùèé îòïðàâêè è ïåðåäàò÷èê ñâîáîäåí è íå æäåò heartbeat
if (p->PacketInWait) {
if (!CANtoRS_Write_Real(&p->bufMSG,p))//îòïðàâèòü íå óäàëîñü?
p->MessDrop2++;
p->PacketInWait=0;//î÷èùàåì áóôåð
}
else{//åñëè ïàêåòà íà îòïðàâê íåò, îáðàáàòûâàåòñÿ âñ¸ îñòàëüíîå. Ìîæíî áû è îáðàáàòûâàòü ñðàçó, íî íå õâàòàåò ðåñóðñîâ
CANtoRS_Receive(p);
p->HeartCounter++; //ñ÷åò÷èê äëÿ HeartBeat
//íå ïîðà ëè îòïðàâèòü HeartBeat?
if (p->HeartCounter>=(CANTORS_HEART_COUNTER_MAX-1)) {
p->HeartCounter=0;
CANtoRS_HeartBeat(p);
}
}
}
/*@}*/