LPC55S16 LINの基本的な使用例
はじめに
この例の目的は、1つのデバイスがマスタとして、もう1つのデバイスがスレーブとして動作する2つのデバイス間の基本的なLIN通信を示すことです。この例で使用する2つのデバイスはLPC55S16 EVKです。
LINマスタは特定のパブリッシャ・フレームとサブスクライバ・フレームを送信します。LINスレーブはマスタデータを検出し、それに応じてデータをフィードバックします。
この記事では主にソフトウェア側に焦点を当てます。ハードウェアについてはhttps://community.nxp.com/t5/LPC-Microcontrollers-Knowledge/LPC54608-LIN-master-basic-usage-sharing/ta-p/1118103をご参照ください。
LINマスタの例
LINマスタはLINパブリッシャ・データとサブスクライバIDデータを送信します。ソフトウェアのコードはSDK_2.8.2_LPCXpresso55S16 usart_interrupt_rb_transferプロジェクトから変更されています。コードの詳細は以下のとおりです。
/* USART callback */
void FLEXCOMM3_IRQHandler()
{
if(DEMO_USART->STAT & USART_STAT_RXBRK_MASK) // detect LIN break
{
Lin_BKflag = 1;
cnt = 0;
state = RECV_DATA;
DisableLinBreak;
}
if((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(DEMO_USART))
{
USART_ClearStatusFlags(DEMO_USART,kUSART_TxError | kUSART_RxError);
rxbuff[cnt] = USART_ReadByte(DEMO_USART);;
switch(state)
{
case RECV_SYN:
if(0x55 == rxbuff[cnt])
{
state = RECV_PID;
}
else
{
state = IDLE;
DisableLinBreak;
}
break;
case RECV_PID:
if(0xAD == rxbuff[cnt])
{
state = SEND_DATA;
}
else if(0XEC == rxbuff[cnt])
{
state = RECV_DATA;
}
else
{
state = IDLE;
DisableLinBreak;
}
break;
case RECV_DATA:
Sub_rxbuff[recdatacnt++]= rxbuff[cnt];
if(recdatacnt >= 3) // 2 Bytes data + 1 Bytes checksum
{
recdatacnt=0;
state = RECV_SYN;
EnableLinBreak;
}
break;
case SEND_DATA:
recdatacnt++;
if(recdatacnt >= 4) // 2 Bytes data + 1 Bytes checksum
{
recdatacnt=0;
state = RECV_SYN;
EnableLinBreak;
}
break;
default:break;
}
cnt++;
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void Lin_Master_Publisher(void)
{
unsigned int i=0;
unsigned char ch =0xa0;//dummy byte
//===============================LIN master send=====================
DEMO_USART->CTL |= USART_CTL_TXBRKEN_MASK;//enable TX break;
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteBlocking(DEMO_USART,&ch,1);//dummy data
break; //just send one byte, otherwise, will send 16 bytes
}
DEMO_USART->CTL &= ~(USART_CTL_TXBRKEN_MASK); //disable TX break
// Send the sync byte 0x55.
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X55);
break; //just send one byte, otherwise, will send 16 bytes
}
//protected ID
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0Xad);
break; //just send one byte, otherwise, will send 16 bytes
}
//Data1
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X01);
break; //just send one byte, otherwise, will send 16 bytes
}
//Data2
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X02);
break; //just send one byte, otherwise, will send 16 bytes
}
//Data3
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X03);
break; //just send one byte, otherwise, will send 16 bytes
}
// checksum byte
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X4c);//0X4c
break; //just send one byte, otherwise, will send 16 bytes
}
}
void Lin_Master_Subscribe(void)
{
unsigned int i=0;
unsigned char ch=0xf0;//dummy byte
DEMO_USART->CTL |= USART_CTL_TXBRKEN_MASK;//enable TX break;
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteBlocking(DEMO_USART,&ch,1);
break; //just send one byte, otherwise, will send 16 bytes
}
DEMO_USART->CTL &= ~(USART_CTL_TXBRKEN_MASK); //disable TX break
// Send the syncy byte 0x55.
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X55);
break; //just send one byte, otherwise, will send 16 bytes
}
//protected ID
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X3C);
break; //just send one byte, otherwise, will send 16 bytes
}
state = RECV_DATA;
}
ここでの主なタスクはLIN breakフィールドの生成と検出でした。
詳しく見てみましょう。パブリッシャおよびサブスクライバ・フレームにLIN breakフィールドを生成するには、まずTx breakを設定し、次にダミーのバイトを送信してからTx breakを無効にします。ダミー・バイトの送信に使用される関数はUSART_WriteBlockingで、USART_WriteByteはダミー・バイト以外のデータ送信に使用されるものです。これは、ダミー・バイトの中でUSART_WriteByteを使用すると他の例のように連続したlowにならなかったためです。この理由はまだ判明していません。分かり次第こちらに更新いたします。
LINスレーブの例
LINスレーブはマスタからLINパブリッシャ・データとサブスクライバIDデータを受信し、必要に応じて応答します。ソフトウェアのコードはSDK_2.8.2_LPCXpresso55S16 usart_interrupt_rb_transferプロジェクトから変更されています。詳細なコードは以下の通りです。
void FLEXCOMM3_IRQHandler()
{
if(DEMO_USART->STAT & USART_STAT_RXBRK_MASK) // detect LIN break
{
Lin_BKflag = 1;
cnt = 0;
state = RECV_SYN;
DisableLinBreak;
}
if((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(DEMO_USART))
{
USART_ClearStatusFlags(DEMO_USART,kUSART_TxError | kUSART_RxError);
rxbuff[cnt] = USART_ReadByte(DEMO_USART);;
switch(state)
{
case RECV_SYN:
if(0x55 == rxbuff[cnt])
{
state = RECV_PID;
}
else
{
state = IDLE;
DisableLinBreak;
}
break;
case RECV_PID:
if(0xAD == rxbuff[cnt])
{
state = RECV_DATA;
}
else if(0X3C == rxbuff[cnt])
{
state = SEND_DATA;
senddata();
}
else
{
state = IDLE;
DisableLinBreak;
}
break;
case RECV_DATA:
recdatacnt++;
if(recdatacnt >= 4) // 3 Bytes data + 1 Bytes checksum
{
recdatacnt=0;
state = RECV_SYN;
EnableLinBreak;
}
break;
default:break;
}
cnt++;
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void senddata(void)
{
{
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X01);
break; //just send one byte, otherwise, will send 16 bytes
}
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X02);
break; //just send one byte, otherwise, will send 16 bytes
}
while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART))
{
USART_WriteByte(DEMO_USART, 0X10);// 0X10 correct 0Xaa wrong
break; //just send one byte, otherwise, will send 16 bytes
}
recdatacnt=0;
state = RECV_SYN;
EnableLinBreak;
}
}
ここにマスターとスレーブのコードを添付いたします。
お役に立てば幸いです。
LPC55xx
記事全体を表示