专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
LIN总线驱动
2019-07-21 04:33
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
4530
7
1138
之前编写lin总线的程序,因为是汽车上用的,刚接触,在学习过程中发现lin的资料论坛中挺少的,所以特意分享下,自己在网上找到的资料,希望大家可以多多交流
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
zhouxb
1楼-- · 2019-07-21 05:50
https://pan.baidu.com/s/1CMYIi-d5LCTlKaiF4yVigQ
加载中...
zhouxb
2楼-- · 2019-07-21 10:19
谁知道如何添加附件
加载中...
zhouxb
3楼-- · 2019-07-21 10:30
精彩回答 2 元偷偷看……
加载中...
zhouxb
4楼-- · 2019-07-21 13:31
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include "LCD.h"
#define BUZZ PORTB_PB5
#define BUZZ_dir DDRB_DDRB5
#define LEDCPU PORTD_PD3
#define LEDCPU_dir DDRD_DDRD3
#define BUS_CLOCK 16000000 //总线频率
#define BAUD 9600 //串口波特率
#define BIT(A,B) ((A>>B)&0x01) // A 为变量
// B 表示A中的第几位
#define ID 0x30 // ID场值为0x30
#define EN PORTD_PD5 //LIN使能
#define EN_dir DDRD_DDRD5
unsigned int x=0;
Bool a;
struct message {
unsigned char identifier;
unsigned char data[8];
};
struct message msg_send;
struct message msg_get;
// 定义LIN状态
enum lin_state { IDLE, _BREAK, SYNCH, PROTECTED_IDENTIFIER, DATA0, DATA1,
DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, CHECKSUM };
// 定义帧结构体
struct frame {
unsigned char protected_id;
unsigned char data[8];
unsigned char check;
enum lin_state state;
unsigned char error;
};
struct frame frame_send,frame_receive;
char *xianshi[3] = {
"飞翔科技开发板",
"接收到的数据为:",
};
/*************************************************************/
/* 初始化锁相环 */
/* 使用外部晶振:16MHz */
/* 设置总线频率:16MHz */
/*************************************************************/
void INIT_PLL(void)
{
CPMUPROT=0x26; //解除时钟配置保护
CPMUOSC_OSCE=1; //使能外部晶振
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
CPMUCLKS &=(~0x40);
CPMUCLKS |= 0x80; //设置PLLCLK为系统时钟
//PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1), fbus=PLLCLK/2
CPMUSYNR=0x01; //SYNDIV的值为1,
CPMUREFDIV = 0x81; //REFDIV的值为1
CPMUPOSTDIV=0x00;
CPMUPLL=0x10;
while(CPMUFLG_LOCK==0); //等待PLLCLK锁定
CPMUPROT=0x00; //使能时钟配置保护
}
/************************************************************/
/* 初始化TIM模块 */
/************************************************************/
void initialize_TIM(void){
TSCR1_TFFCA = 1; // 定时器标志位快速清除
TSCR1_TEN = 1; // 定时器使能位. 1=允许定时器正常工作; 0=使主定时器不起作用(包括计数器)
TIOS = 0xff; //指定所有通道为输出比较方式
TCTL1 = 0x00; // 后四个通道设置为定时器与输出引脚断开
TCTL2 = 0x00; // 前四个通道设置为定时器与输出引脚断开
TIE = 0x00; // 禁止所有通道定时中断
TSCR2 = 0x06; // 预分频系数pr2-pr0:110,时钟周期为4us,
TFLG1 = 0xff; // 清除各IC/OC中断标志位
TFLG2 = 0xff; // 清除自由定时器中断标志位
}
/*************************************************************/
/* 初始化LIN */
/*************************************************************/
void INIT_LIN(void)
{
unsigned char i;
SCI0BD = BUS_CLOCK/16/BAUD; //设置SCI0波特率为9600
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验
SCI0CR2 = 0x2c; //允许接收和发送数据,允许接收中断功能
SCI0SR2_BRK13 = 1;
frame_receive.protected_id=0;
frame_receive.state=IDLE;
frame_receive.error=0;
frame_receive.check=0;
for (i=0;i<8;i++)
frame_receive.data[i]=0;
EN_dir=1;
EN=1;
}
/*************************************************************/
/* 计算奇偶校验位 */
/*************************************************************/
unsigned char LINCalcParity(unsigned char id)
{
unsigned char parity, p0,p1;
parity=id;
p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6; //偶校验位
p1=(!(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7; //奇校验位
parity|=(p0|p1);
return parity;
}
/*************************************************************/
/* 计算和校验位 */
/*************************************************************/
unsigned char LINCalcChecksum(unsigned char *data)
{
unsigned int sum = 0;
unsigned char i;
for(i = 0; i < 8; i++)
{
sum += data[i];
if(sum&0xFF00)
sum = (sum&0x00FF) + 1;
}
sum ^= 0x00FF;
return (unsigned char)sum;
}
/*************************************************************/
/* LIN接收字节函数 */
/*************************************************************/
Bool LINGetChar(void)
{
unsigned volatile char ch;
// LIN接收通道状态
switch(frame_receive.state)
{
case IDLE:
if(!(SCI0SR1&0x22))
return(FALSE);
if(SCI0DRL)
return(FALSE);
break;
case _BREAK:
if(!(SCI0SR1&0x20))
return(FALSE);
if(SCI0DRL != 0x55)
return(FALSE);
break;
case SYNCH:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.protected_id = ch;
break;
case PROTECTED_IDENTIFIER:
case DATA0:
case DATA1:
case DATA2:
case DATA3:
case DATA4:
case DATA5:
case DATA6:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.data[frame_receive.state-PROTECTED_IDENTIFIER] = ch;
break;
case DATA7:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.check = ch;
break;
case CHECKSUM:
return(FALSE);
}
frame_receive.state+=1;
return(TRUE);
}
/************************************************************/
/* 在液晶上显示接收到的数据 */
/************************************************************/
void play_data(void)
{
unsigned char l;
write_command(0x8A);
for(l=0;l<8;l++)
write_Data(frame_receive.data[l]);
}
/************************************************************/
/* LIN接收数据 */
/************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt void LINreceive(void)
{
if(!LINGetChar())
{
frame_receive.error = 1;
frame_receive.state = IDLE;
}
}
#pragma CODE_SEG DEFAULT
/*************************************************************/
/* 主函数 */
/*************************************************************/
void main(void) {
DisableInterrupts;
INIT_PLL();
initialize_TIM();
INIT_LIN();
INIT_PORT();
LEDCPU_dir=1;
LEDCPU=0;
BUZZ_dir=1;
BUZZ=0;
EnableInterrupts;
for(;;)
{
if(frame_receive.state == CHECKSUM)
{
//判断数据接收是否正确
if((frame_receive.protected_id == LINCalcParity(ID))&&
(frame_receive.check == LINCalcChecksum(frame_receive.data)))
{
LEDCPU=~LEDCPU;
lcd_clear();
lcd_string(0,0,xianshi[0]);
lcd_string(1,0,xianshi[1]);
play_data(); //显示接收到的数据
}
frame_receive.state = IDLE;
}
}
}
加载中...
wfl1287
5楼-- · 2019-07-21 14:04
谢谢楼主分享
加载中...
小小的人
6楼-- · 2019-07-21 14:44
感谢楼主
加载中...
1
2
下一页
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#include "derivative.h" /* derivative-specific definitions */
#include "LCD.h"
#define BUZZ PORTB_PB5
#define BUZZ_dir DDRB_DDRB5
#define LEDCPU PORTD_PD3
#define LEDCPU_dir DDRD_DDRD3
#define BUS_CLOCK 16000000 //总线频率
#define BAUD 9600 //串口波特率
#define BIT(A,B) ((A>>B)&0x01) // A 为变量
// B 表示A中的第几位
#define ID 0x30 // ID场值为0x30
#define EN PORTD_PD5 //LIN使能
#define EN_dir DDRD_DDRD5
unsigned int x=0;
Bool a;
struct message {
unsigned char identifier;
unsigned char data[8];
};
struct message msg_send;
struct message msg_get;
// 定义LIN状态
enum lin_state { IDLE, _BREAK, SYNCH, PROTECTED_IDENTIFIER, DATA0, DATA1,
DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, CHECKSUM };
// 定义帧结构体
struct frame {
unsigned char protected_id;
unsigned char data[8];
unsigned char check;
enum lin_state state;
unsigned char error;
};
struct frame frame_send,frame_receive;
char *xianshi[3] = {
"飞翔科技开发板",
"接收到的数据为:",
};
/*************************************************************/
/* 初始化锁相环 */
/* 使用外部晶振:16MHz */
/* 设置总线频率:16MHz */
/*************************************************************/
void INIT_PLL(void)
{
CPMUPROT=0x26; //解除时钟配置保护
CPMUOSC_OSCE=1; //使能外部晶振
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
CPMUCLKS &=(~0x40);
CPMUCLKS |= 0x80; //设置PLLCLK为系统时钟
//PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1), fbus=PLLCLK/2
CPMUSYNR=0x01; //SYNDIV的值为1,
CPMUREFDIV = 0x81; //REFDIV的值为1
CPMUPOSTDIV=0x00;
CPMUPLL=0x10;
while(CPMUFLG_LOCK==0); //等待PLLCLK锁定
CPMUPROT=0x00; //使能时钟配置保护
}
/************************************************************/
/* 初始化TIM模块 */
/************************************************************/
void initialize_TIM(void){
TSCR1_TFFCA = 1; // 定时器标志位快速清除
TSCR1_TEN = 1; // 定时器使能位. 1=允许定时器正常工作; 0=使主定时器不起作用(包括计数器)
TIOS = 0xff; //指定所有通道为输出比较方式
TCTL1 = 0x00; // 后四个通道设置为定时器与输出引脚断开
TCTL2 = 0x00; // 前四个通道设置为定时器与输出引脚断开
TIE = 0x00; // 禁止所有通道定时中断
TSCR2 = 0x06; // 预分频系数pr2-pr0:110,时钟周期为4us,
TFLG1 = 0xff; // 清除各IC/OC中断标志位
TFLG2 = 0xff; // 清除自由定时器中断标志位
}
/*************************************************************/
/* 初始化LIN */
/*************************************************************/
void INIT_LIN(void)
{
unsigned char i;
SCI0BD = BUS_CLOCK/16/BAUD; //设置SCI0波特率为9600
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验
SCI0CR2 = 0x2c; //允许接收和发送数据,允许接收中断功能
SCI0SR2_BRK13 = 1;
frame_receive.protected_id=0;
frame_receive.state=IDLE;
frame_receive.error=0;
frame_receive.check=0;
for (i=0;i<8;i++)
frame_receive.data[i]=0;
EN_dir=1;
EN=1;
}
/*************************************************************/
/* 计算奇偶校验位 */
/*************************************************************/
unsigned char LINCalcParity(unsigned char id)
{
unsigned char parity, p0,p1;
parity=id;
p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6; //偶校验位
p1=(!(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7; //奇校验位
parity|=(p0|p1);
return parity;
}
/*************************************************************/
/* 计算和校验位 */
/*************************************************************/
unsigned char LINCalcChecksum(unsigned char *data)
{
unsigned int sum = 0;
unsigned char i;
for(i = 0; i < 8; i++)
{
sum += data[i];
if(sum&0xFF00)
sum = (sum&0x00FF) + 1;
}
sum ^= 0x00FF;
return (unsigned char)sum;
}
/*************************************************************/
/* LIN接收字节函数 */
/*************************************************************/
Bool LINGetChar(void)
{
unsigned volatile char ch;
// LIN接收通道状态
switch(frame_receive.state)
{
case IDLE:
if(!(SCI0SR1&0x22))
return(FALSE);
if(SCI0DRL)
return(FALSE);
break;
case _BREAK:
if(!(SCI0SR1&0x20))
return(FALSE);
if(SCI0DRL != 0x55)
return(FALSE);
break;
case SYNCH:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.protected_id = ch;
break;
case PROTECTED_IDENTIFIER:
case DATA0:
case DATA1:
case DATA2:
case DATA3:
case DATA4:
case DATA5:
case DATA6:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.data[frame_receive.state-PROTECTED_IDENTIFIER] = ch;
break;
case DATA7:
if(!(SCI0SR1&0x20))
return(FALSE);
ch = SCI0DRL;
frame_receive.check = ch;
break;
case CHECKSUM:
return(FALSE);
}
frame_receive.state+=1;
return(TRUE);
}
/************************************************************/
/* 在液晶上显示接收到的数据 */
/************************************************************/
void play_data(void)
{
unsigned char l;
write_command(0x8A);
for(l=0;l<8;l++)
write_Data(frame_receive.data[l]);
}
/************************************************************/
/* LIN接收数据 */
/************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt void LINreceive(void)
{
if(!LINGetChar())
{
frame_receive.error = 1;
frame_receive.state = IDLE;
}
}
#pragma CODE_SEG DEFAULT
/*************************************************************/
/* 主函数 */
/*************************************************************/
void main(void) {
DisableInterrupts;
INIT_PLL();
initialize_TIM();
INIT_LIN();
INIT_PORT();
LEDCPU_dir=1;
LEDCPU=0;
BUZZ_dir=1;
BUZZ=0;
EnableInterrupts;
for(;;)
{
if(frame_receive.state == CHECKSUM)
{
//判断数据接收是否正确
if((frame_receive.protected_id == LINCalcParity(ID))&&
(frame_receive.check == LINCalcChecksum(frame_receive.data)))
{
LEDCPU=~LEDCPU;
lcd_clear();
lcd_string(0,0,xianshi[0]);
lcd_string(1,0,xianshi[1]);
play_data(); //显示接收到的数据
}
frame_receive.state = IDLE;
}
}
}
一周热门 更多>