分享一些LIN的知识,我一开始是写的寄存器版本的从机通讯,但一直调试不通,出现了以下问题:
1.在不开启中断的情况下,能发送数据,但开了中断就无法发送。
2.一直无法检测到LIN断开符,即同步间隔段。
后来通过查手册发现了问题所在,就改用了固件库函数版本,至于问题是什么,后面会提,先介绍一下STM8串口的LIN模式。
相对于STM32,STM8在LIN通讯方面更有优势,因为STM8对LIN做了更详细的设计,通过寄存器可以更方便快捷地进行LIN通讯。STM8的LIN通讯可以配置主从模式,有自动重同步功能,在每次接收到LIN同步域后自动调整波特率发生器,还能LIN标识符奇偶校验自动检测等等。
目录
1. 主模式
2. 自动重同步功能禁用的从模式
3. 自动重同步功能启用的从模式
4. 从模式的寄存器配置
5. 寄存器版本代码问题所在
6. 从模式的库函数配置
7. 串口中断函数
UART初始化:
1. 设置UART_BRR2和UART_BRR1来选择期望的波特率。
2. 将UART_CR3的LINEN位置1来使能LIN模式。
3. 将UART_CR2的TEN位和REN位置1来使能发送器和接收器。
UART初始化:
1. 设置UART_BRR2和UART_BRR1来选择期望的波特率。
2. 将UART_CR2的TEN位和REN位置1来使能发送器和接收器。
3. 使能UART_CR6的LSLV位
4. 将UART_CR3的LINEN位置1来使能LIN模式
此模式与上面描述的从模式类似,只是要额外把LASE位置1使能的自动重同步功能。在此模式下, UART在每次接收到LIN同步域后,调整波特率发生器
根据上面的步骤进行配置就好,如果想要开启接收中断或LIN断开符检测中断,只需要置位相关寄存器即可。
一般置位只需 UART1->CR1 |= 0x01 ,这样UART1->CR1寄存器的第1位便置1了,库函数的话直接调用中断使能函数即可(提一嘴,无论是寄存器版本还是库函数版本,一定一定都要看手册进行配置)。
中断函数是 INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18),18是UART1接收寄存器满的中断向量号。
先看一下手册:
我所使用的STM8S003F4P6单片机只有一个UART口,即UART1,是不支持LIN从模式的,所以我寄存器配来配去LIN的从机模式都是不行的,因为它TM的根本就没有从机模式,哭了。。。所以大家下次写代码的时候请请请请请请一定要先看清楚手册!!!
虽然它没有从模式,但它有主模式阿!主模式一样可以检测LIN断开符,一样可以接收发送数据,我把主模式当从模式用,不知道这样做是不是有问题的,但我功能最后是成功实现了。
注:库函数版本不用初始化GPIO口,不用使能UART。
//LIN初始化
void LIN_Init(uint32_t bau){
/* 初始化UART1 */
UART1_DeInit();
UART1_Init((u32)bau, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO,UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE); //开启接收中断
/* 启用LIN模式 */
UART1_LINBreakDetectionConfig(UART1_LINBREAKDETECTIONLENGTH_11BITS);
UART1_LINCmd(ENABLE);
UART1_ITConfig(UART1_IT_LBDF, ENABLE); //开启检测断路中断
}
初始化代码很短,因为少了主从模式的配置,但主从的配置也很简单,只需一条库函数:
UART2_LINConfig(UART2_LIN_MODE_MASTER, UART2_LIN_AUTOSYNC_DISABLE, UART2_LIN_DIVUP_LBRR1); //主模式 - 禁止自动同步 - LDIV在对BRR1写入以后立即更新
具体参数配置可以自己看函数介绍。
仅供参考:
//串口中断函数
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
uint8_t ReceiveData = 0;
if(UART1_GetITStatus(UART1_IT_LBDF) == SET){ //检测断路中断
LIN_RingBUF_ClearRxMsg(&LIN_RxDataBuff); //清空当前缓冲区
UART1->SR;
UART1->DR;
LIN_RxStateGet = SYNCH_GET; //更新LIN接收状态
UART1_ClearITPendingBit(UART1_IT_LBDF);
UART1_ClearITPendingBit(UART1_IT_RXNE);
return;
}
if(UART1_GetITStatus(UART1_IT_RXNE) == SET){ //接收中断
ReceiveData = UART1_ReceiveData8(); //返回USARTx外设最近接收到的数据。
if ((UART1->SR & 0x02) != 0x02){ //判断帧错误
if ((ReceiveData==0x55)&&(LIN_RxStateGet==BREAK_GET)){ //处理无同步间隔信号的LIN数据
LIN_RingBUF_ClearRxMsg(&LIN_RxDataBuff); //清空当前缓冲区//清空当前缓冲区
LIN_RxStateGet = SYNCH_GET;
return;
}
LIN_MasterRxMsg(ReceiveData); //消息处理函数
}
UART1_ClearITPendingBit(UART1_IT_RXNE);
}
}
有需要的可以找我要代码!我是刚入门LIN通讯,能力不足!希望跟大家一起学习!
过几天我再写一篇STM32F103的LIN通讯文章,会贴出完整代码,包括LIN的接收发送,以及串口接收环形缓冲区!请多多支持!!!
注:STM8的接收发送串口接收环形缓冲区等内容编写跟STM32其实是一样的,只是初始化和调用的一些函数名不太一样而已,看懂了32的,8的自然也会写。
已更新 :STM32F103 -- LIN从机通讯 -- 程序代码详细讲解(2万字长文) ,下面是链接!!!
http://t.csdn.cn/IRkcc