#申请原创#
前言
LIN是一种主要用于汽车的低速通信,目前主要用在汽车的车门,车窗,天窗等控制器的通信,这些一般对速度要求不高。并且LIN通信的硬件是基于串口硬件,可以极大的缩减开发成本。AC7802X中的UART集成了LIN功能,本文将对AC7802X的LIN功能做分析以及测试。
关于LIN协议,本文不做介绍。帧格式如下:
1 硬件分析
首先查看用户手册,了解到AC7802x的LIN功能是非硬件LIN,是基于UART基础上实现的软件LIN,如下:
下图介绍了如何使用LIN功能:
关于LIN接口,AC780X板子上面已经扩展出来了,PA7和PA8分别作为LIN总线的TX和RX接口,这两根线通过一个LIN收发器连接到了LIN总线。
调试LIN功能需要一个LIN调试设备,本文使用的是PEAK-LIN作为调试设备,监控单片机上LIN发送的数据。
2 软件分析
官方提供了LIN测试代码,本文测试了Lin_Base工程,该工程中,单片机上的LIN是作为主机工作的,会发送LIN帧头以及LIN响应,从机作为接收方,只需要接收主机的数据即可,本文的从机就是PRAK-LIN。
2.1 初始化代码
初始化代码主要是初始化UART功能以及相应的引脚,使能UART的LIN功能以及波特率,中断等信息,不做过多说明。
void LIN_InitLin(uint8_t mode, uint8_t schTblIdx, uint16_t baudrate)
{
UART_ConfigType uartConfig;
memset((void *)&uartConfig, 0, sizeof(UART_ConfigType));
/*!初始化LIN的引脚功能
包括RX/TX及LIN的收发器引脚*/
GPIO_SetFunc(SWLIN_RX, RXPinFunc);
GPIO_SetFunc(SWLIN_TX, TXPinFunc);
GPIO_SetDir(SWLIN_SLP, GPIO_OUT);
GPIO_SetPinLevel(SWLIN_SLP, GPIO_LEVEL_HIGH);
/*!初始化Uart_LIN及相关参数
包括波特率及其他配置*/
uartConfig.baudrate = baudrate;
uartConfig.dataBits = UART_WORD_LEN_8BIT;
uartConfig.stopBits = UART_STOP_1BIT;
uartConfig.parity = UART_PARI_NO;
uartConfig.fifoByteEn = DISABLE;
uartConfig.sampleCnt = UART_SMP_CNT0;
uartConfig.callBack = UartLIN_Handler;
UART_Init(UART_LIN, &uartConfig);
/*!配置LIN需要使能的功能*/
UART_SetLIN(UART_LIN, UART_LINCR_LINEN_Msk | UART_LINCR_LBRKIE_Msk | UART_LINCR_LBRKDL_Msk);
/*!配置LIN模块相关中断*/
UART_SetRXNEInterrupt(UART_LIN, DISABLE);
UART_SetTXEInterrupt(UART_LIN, DISABLE);
NVIC_ClearPendingIRQ(UART_LIN_IRQn);
NVIC_EnableIRQ(UART_LIN_IRQn);
}
2.2 报文传输函数
如下,因为不是硬件LIN,所以LIN协议中的同步场和校验和场都需要软件来填写:
- `g_LinDataTx[0] = 0x55;`是同步场报文,固定为0x55
- `g_LinDataTx[1] = 0x50;`是标识符场,也就是报文的PID,前六位是ID,后两位是奇偶校验位,计算方式见下图,所以真实ID为0x10。
- `g_LinDataTx[2]~g_LinDataTx[9]`是8位数据,导入的数据从0开始依次向上加
- 接下来是计算校验和,这里使用的是经典校验和,增强检验和需要加上PID段,计算方式是就爱那个8位数据依次加起来,如果大于了0xFF,则丢掉高位,保留低两位。
- 最后将校验和放到 `g_LinDataTx[2]`中
- 以上步骤就组成了一个完整的LIN报文。
- 最后使用 `UART_SendData(UART0, g_LinDataTx[j]);`依次将数据通过串口发送出去就完成了LIN报文的发送。
void SendSimpleLinMessage(void)
{
static uint16_t checksum = 0;
static uint8_t i = 0, a = 0;
static uint8_t j = 0;
a++;
UART_SendLINBreak(UART0);
/*!LIN数据填充,包括同步场和校验场*/
g_LinDataTx[0] = 0x55;
g_LinDataTx[1] = 0x50;
g_LinDataTx[2] = a+1;
g_LinDataTx[3] = a+2;
g_LinDataTx[4] = a+3;
g_LinDataTx[5] = a+4;
g_LinDataTx[6] = a+5;
g_LinDataTx[7] = a+6;
g_LinDataTx[8] = a+7;
g_LinDataTx[9] = a+8;
/*!增强型校验和需要加上ID*/
checksum = g_LinDataTx[1];
for (i = 2; i < 10; i++)
{
checksum += g_LinDataTx[i];
if (checksum >= 0x100)
{
checksum -= 0xFF;
}
}
checksum ^= 0xFF;
/*!数据校验和*/
g_LinDataTx[10] = checksum;
/*!发送同步域,ID,数据域,校验和*/
for(j = 0;j < 11;j++)
{
UART_SendData(UART0, g_LinDataTx[j]);
}
checksum = 0;
}
2.3 中断
本例中其实没有用中断,中断主要是用来处理数据接收以及传输错误,下面是示例代码,中断没有使用,如果要使用LIN数据接收的功能,需要使用中断UART_LSR0_DR_Msk。
void UartLIN_Handler(void *device, uint32_t wpara, uint32_t lpara)
{
/*!Receive break field*/
if (0 != (lpara & UART_LSR1_FBRK_Msk))
{
/*!<write 1 to clear break status*/
UART_LIN->LSR1 |= UART_LSR1_FBRK_Msk;
}
/*!Receive data*/
if (0 != (wpara & UART_LSR0_DR_Msk))
{
}
/*!Transmit data done*/
if (0 != (wpara & UART_LSR0_THRE_Msk))
{
}
}
2.4 主函数
主函数逻辑如下:
- `LIN_InitLin(MASTER_MODE, 0, 19200);`是初始化LIN作为主模式,并且设置波特率为19200(LIN支持的最大波特率)
- `SendSimpleLinMessage()`发送数据
int main(void)
{
InitDelay();
InitDebug();
/*!for master initlin*/
LIN_InitLin(MASTER_MODE, 0, 19200);
while(1)
{
SendSimpleLinMessage();
mdelay(500);
}
}
3 实验结果
如下图,trace界面会收到单片机发送的LIN报文,每个500ms会收到一次数据,数据ID为0x10,数据长度为8,每次接受到的数据会一次增大一位,与之前的分析吻合。
总结
虽然AC7802X没有集成完全的硬件LIN,但是在UART的基础上增加了LIN相关寄存器,可以用于软件扩展LIN功能,也满足了大部分使用场景,可以用于这在LIN通信,而且操作相对简单,还是很不错的。
|