首页
游戏
影视
直播
广播
听书
音乐
图片
更多
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
Search
1
科普:Memory Compiler生成的Register file和SRAM有何区别?
40 阅读
2
在IC617中进行xa+vcs数模混仿
35 阅读
3
virtuoso和empyrean alps模拟仿真和混仿教程
32 阅读
4
文档内容搜索哪家强? 15款文件搜索软件横向评测
19 阅读
5
vcs debug rtl或者netlist 中的loop
17 阅读
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
登录
Search
标签搜索
python
Docker
vcs
PyQT
STM32
cadence
linux
systemverilog
EDA
Alist
vscode
uos
package
C
QT
CXL
sed
sv
webdav
FPGA
bennyhe
累计撰写
341
篇文章
累计收到
31
条评论
首页
栏目
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
页面
游戏
影视
直播
广播
听书
音乐
图片
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
搜索到
15
篇与
的结果
2025-07-18
Vscode自动生成verilog例化
前言veirlog模块例化的时候,辣么多的信号端子,手动例化又慢又容易出错,葵花妈妈开课啦,孩子手残老犯错怎么办?当然是脚本一劳永逸,妈妈再也不担心手残党。流程(1)在vscode中安装如下插件。(2)在电脑中安装python3以上的环境。下载地址:https://www.python.org/downloads/release/python-373/安装记得一定要勾选添加路径,记得管理员安装。重启你的电脑。在cmd窗口输入python即可验证是否安装成功!(3)安装chardet。为确保插件可用,这个需要安装。参考链接:https://blog.csdn.net/sinat_28631741/article/details/80483064方式一 源码按照: 第一步:下载压缩文件,例如: 'chardet-3.0.4.tar.gz'; 第二步:解压文件到python安装位置下的‘site-packages’目录下,例如:‘D:\python2.7\Lib\site-packages’; 第三步:打开终端命令窗口,进入解压的‘chardet’目录下,执行命令:python setup.py install (4)修改插件的原始py文件,觉得开发者的py有瑕疵,让帅气的同事重新整了个,把以下代码替换进原始py文件即可。在打开v文件的vscode下按ctrl+p,输入instance可出现下述界面。替换此py文件的代码即可。#! /usr/bin/env python ''' vTbgenerator.py -- generate verilog module Testbench generated bench file like this: fifo_sc #( .DATA_WIDTH ( 8 ), .ADDR_WIDTH ( 8 ) ) u_fifo_sc ( .CLK ( CLK ), .RST_N ( RST_N ), .RD_EN ( RD_EN ), .WR_EN ( WR_EN ), .DIN ( DIN [DATA_WIDTH-1 :0] ), .DOUT ( DOUT [DATA_WIDTH-1 :0] ), .EMPTY ( EMPTY ), .FULL ( FULL ) ); Usage: python vTbgenerator.py ModuleFileName.v ''' import random import re import sys from queue import Queue import chardet def delComment(Text): """ removed comment """ single_line_comment = re.compile(r"//(.*)$", re.MULTILINE) multi_line_comment = re.compile(r"/\*(.*?)\*/", re.DOTALL) Text = multi_line_comment.sub('\n', Text) Text = single_line_comment.sub('\n', Text) return Text def delBlock(Text): """ removed task and function block """ Text = re.sub(r'\Wtask\W[\W\w]*?\Wendtask\W', '\n', Text) Text = re.sub(r'\Wfunction\W[\W\w]*?\Wendfunction\W', '\n', Text) return Text def findName(inText): """ find module name and port list""" p = re.search(r'([a-zA-Z_][a-zA-Z_0-9]*)\s*', inText) mo_Name = p.group(0).strip() return mo_Name def paraDeclare(inText, portArr): """ find parameter declare """ pat = r'\s' + portArr + r'\s[\w\W]*?[;,)]' ParaList = re.findall(pat, inText) return ParaList def portDeclare(inText, portArr): """find port declare, Syntax: input [ net_type ] [ signed ] [ range ] list_of_port_identifiers return list as : (port, [range]) """ port_definition = re.compile( r'\b' + portArr + r''' (\s+(wire|reg|logic|interface)\s+)* (\s*signed\s+)* (\s*\[.*?:.*?\]\s*)* (?P<port_list>.*?) (?= \binput\b | \boutput\b | \binout\b | ; | \) ) ''', re.VERBOSE | re.MULTILINE | re.DOTALL ) pList = port_definition.findall(inText) t = [] for ls in pList: if len(ls) >= 2: t = t + portDic(ls[-2:]) return t def portDic(port): """delet as : input a =c &d; return list as : (port, [range]) """ pRe = re.compile(r'(.*?)\s*=.*', re.DOTALL) pRange = port[0] pList = port[1].split(',') pList = [i.strip() for i in pList if i.strip() != ''] pList = [(pRe.sub(r'\1', p), pRange.strip()) for p in pList] return pList def formatPort(AllPortList, isPortRange=1): PortList = AllPortList str = '' if PortList != []: l1 = max([len(i[0]) for i in PortList])+2 l3 = max(18, l1) strList = [] str = ',\n'.join([' ' * 4 + '.' + i[0].ljust(l3) + '(' + (i[0]) + ')' for i in AllPortList]) strList = strList + [str] str = ',\n\n'.join(strList) return str def formatDeclare(PortList, portArr, initial=""): str = '' if PortList != []: str = '\n'.join([portArr.ljust(4) + ' '+(i[1]+min(len(i[1]), 1)*' ' + i[0]) + ';' for i in PortList]) return str def formatPara(ParaList): paraDec = '' paraDef = '' if ParaList != []: s = '\n'.join(ParaList) pat = r'([a-zA-Z_][a-zA-Z_0-9]*)\s*=\s*([\w\W]*?)\s*[;,)]' p = re.findall(pat, s) l1 = max([len(i[0]) for i in p]) l2 = max([len(i[1]) for i in p]) paraDec = '\n'.join(['parameter %s = %s;' % (i[0].ljust(l1 + 1), i[1].ljust(l2)) for i in p]) paraDef = '#(\n' + ',\n'.join([' .' + i[0].ljust(l1 + 1) + '( ' + i[1].ljust(l2)+' )' for i in p]) + ')\n' return paraDec, paraDef def portT(inText, ioPadAttr): x = {} count_list = [] order_list = [] for i in ioPadAttr: p = port_index_list(inText, i) for j in p: count_list.append(j) x[j] = i count_list = quick_sort(count_list, 0, len(count_list)-1) for c in count_list: order_list.append(x.get(c)) return order_list def quick_sort(myList, start, end): if start < end: i, j = start, end base = myList[i] while i < j: while (i < j) and (myList[j] >= base): j = j - 1 myList[i] = myList[j] while (i < j) and (myList[i] <= base): i = i + 1 myList[j] = myList[i] myList[i] = base quick_sort(myList, start, i - 1) quick_sort(myList, j + 1, end) return myList def formatPort_order(padAttr, orderList): for p in padAttr: q = Queue() for i in padAttr.get(p): q.put(i) padAttr[p] = q AllPortList = [] for o in orderList: AllPortList.append(padAttr.get(o).get()) return AllPortList def port_index_list(intext, text): l = [] t = intext index = t.find(text) while index > -1: t = t.replace(text, random_str(len(text)), 1) l.append(index) index = t.find(text) return l def random_str(size): s = '' for i in range(size): s += str(random.randint(0, 9)) return s def getPortMap(AllPortList, ioPadAttr): if len(AllPortList) != len(ioPadAttr): return p_map = {} for i in range(len(AllPortList)): p_map[ioPadAttr[i]] = AllPortList[i] return p_map def writeTestBench(input_file): """ write testbench to file """ with open(input_file, 'rb') as f: f_info = chardet.detect(f.read()) f_encoding = f_info['encoding'] with open(input_file, encoding=f_encoding) as inFile: inText = inFile.read() # removed comment,task,function inText = delComment(inText) inText = delBlock(inText) # moduel ... endmodule # moPos_begin = re.search(r'(\b|^)module\b', inText).end() moPos_end = re.search(r'\bendmodule\b', inText).start() inText = inText[moPos_begin:moPos_end] name = findName(inText) paraList = paraDeclare(inText, 'parameter') paraDec, paraDef = formatPara(paraList) ioPadAttr = ['input', 'output', 'inout','interface'] orlder = portT(inText, ioPadAttr) input = portDeclare(inText, ioPadAttr[0]) output = portDeclare(inText, ioPadAttr[1]) inout = portDeclare(inText, ioPadAttr[2]) interface = portDeclare(inText, ioPadAttr[3]) portList = formatPort(formatPort_order( getPortMap([input, output, inout,interface], ioPadAttr), orlder)) input = formatDeclare(input, 'reg') output = formatDeclare(output, 'wire') inout = formatDeclare(inout, 'wire') interface = formatDeclare(interface, 'wire') # write Instance # module_parameter_port_list if(paraDec != ''): print("// %s Parameters\n%s\n" % (name, paraDec)) # list_of_port_declarations #print("// %s Inputs\n%s\n" % (name, input)) #print("// %s Outputs\n%s\n" % (name, output)) #if(inout != ''): # print("// %s Bidirs\n%s\n" % (name, inout)) print("\n") # UUT print("%s %s inst_%s (\n%s\n);" % (name, paraDef, name, portList)) if __name__ == '__main__': writeTestBench(sys.argv[1])(5)享受一下吧。比如我们有如下代码:crtl+p,输入instance,按回车即可。 复制粘贴大发好。以上。转载于:https://www.cnblogs.com/kingstacker/p/9944259.html有道云笔记2021-11-02 11:37:58
2025年07月18日
2 阅读
0 评论
0 点赞
2025-07-18
STM32之霍尔传感器模块
一、简介本文介绍如何在STM32上使用霍尔传感器模块。二、实验平台库版本:STM32F10x_StdPeriph_Lib_V3.5.0编译软件:MDK4.53硬件平台:STM32开发板(主芯片stm32f103c8t6)仿真器:JLINK三、版权声明博主:甜甜的大香瓜声明:喝水不忘挖井人,转载请注明出处。原文地址:http://blog.csdn.NET/feilusia联系方式:897503845@qq.com香瓜BLE之CC2541群:127442605香瓜BLE之CC2640群:557278427香瓜BLE之Android群:541462902香瓜单片机之STM8/STM32群:164311667甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i四、实验前提1、在进行本文步骤前,请先阅读以下博文:暂无2、在进行本文步骤前,请先 实现以下博文:暂无五、基础知识1、霍尔传感器是什么?答:霍尔传感器是根据霍尔效应制作的一种磁场传感器。用磁铁去靠近霍尔传感器时,霍尔传感器的引脚电平会产生变化。2、霍尔传感器主要用在什么地方?答:霍尔传感器可测速、计数、限位上。举例限位功能:两个霍尔传感器形成45°的夹角,电机边缘粘着一个磁铁,一旦电机转动导致磁铁触发任意其中一个霍尔传感器,则STM32检测到触发后立刻停止电机,不能再继续往此方向转动。以此达到限制电机转动角度的作用。3、本文使用的是什么霍尔传感器模块?答:香瓜买的霍尔传感器模块一共有四个引脚,GND、VCC、D0、A0。其中只需要用到三根线,GND、VCC、D0。(A0不知做啥用的,计数?)使用方法:1)5V供电。2)用跳线连接D0和STM32的IO口(本文连接的是PA11)。3)D0默认是高电平,但磁铁的特定一面(磁铁另一面无用)去靠近霍尔传感器模块时,D0会被拉低。4、霍尔传感器与限位开关有什么区别?答:1)限位开关①优点:无功耗。②缺点:易损坏。2)霍尔传感器①优点:不易损坏。②缺点:有功耗。六、实验步骤1、编写并添加霍尔传感器驱动1)编写驱动GUA_Hall_Sensor.c(存放在“……\HARDWARE”) //****************************************************************************** //name: GUA_Hall_Sensor.c //introduce: 霍尔传感器驱动 //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group 香瓜单片机之STM8/STM32(164311667) //changetime: 2017.03.06 //****************************************************************************** #include"stm32f10x.h" #include"GUA_Hall_Sensor.h" /*********************宏定义************************/ //霍尔传感器引脚 #define GUA_HALL_SENSOR_PORT GPIOA #define GUA_HALL_SENSOR_PIN GPIO_Pin_11 //消抖总次数 #define GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT 500000 /*********************内部变量************************/ static GUA_U32 sGUA_Hall_Sensor_DisapperasShakes_IdleCount = 0; //消抖时的空闲状态计数值 static GUA_U32 sGUA_Hall_Sensor_DisapperasShakes_TriggerCount = 0; //消抖时的触发状态计数值 /*********************内部函数************************/ staticvoidGUA_Hall_Sensor_IO_Init(void); //****************************************************************************** //name: GUA_Hall_Sensor_IO_Init //introduce: 霍尔传感器的IO初始化 //parameter: none //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group 香瓜单片机之STM8/STM32(164311667) //changetime: 2017.03.06 //****************************************************************************** staticvoidGUA_Hall_Sensor_IO_Init(void) { //IO结构体 GPIO_InitTypeDef GPIO_InitStructure; //时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //霍尔IO配置 GPIO_InitStructure.GPIO_Pin = GUA_HALL_SENSOR_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GUA_HALL_SENSOR_PORT, &GPIO_InitStructure); } //****************************************************************************** //name: GUA_Hall_Sensor_Check_Pin //introduce: 霍尔传感器检测触发状态 //parameter: none //return: GUA_HALL_SENSOR_STATUS_IDLE or GUA_HALL_SENSOR_STATUS_TRIGGER //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group 香瓜单片机之STM8/STM32(164311667) //changetime: 2017.03.06 //****************************************************************************** GUA_U8 GUA_Hall_Sensor_Check_Pin(void) { //没触发 if(GPIO_ReadInputDataBit(GUA_HALL_SENSOR_PORT, GUA_HALL_SENSOR_PIN) == SET) { //计数 sGUA_Hall_Sensor_DisapperasShakes_IdleCount++; sGUA_Hall_Sensor_DisapperasShakes_TriggerCount = 0; //判断计数是否足够 if(sGUA_Hall_Sensor_DisapperasShakes_IdleCount >= GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT) { return GUA_HALL_SENSOR_STATUS_IDLE; } } //触发 else { //计数 sGUA_Hall_Sensor_DisapperasShakes_IdleCount = 0; sGUA_Hall_Sensor_DisapperasShakes_TriggerCount++; //判断计数是否足够 if(sGUA_Hall_Sensor_DisapperasShakes_TriggerCount >= GUA_HALL_SENSOR_DISAPPERAS_SHAKS_COUNT) { return GUA_HALL_SENSOR_STATUS_TRIGGER; } } return GUA_HALL_SENSOR_STATUS_DISAPPERAS_SHAKS; } //****************************************************************************** //name: GUA_Limit_Switch_Init //introduce: 霍尔传感器初始化 //parameter: none //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group 香瓜单片机之STM8/STM32(164311667) //changetime: 2017.03.06 //****************************************************************************** voidGUA_Hall_Sensor_Init(void) { //初始化IO GUA_Hall_Sensor_IO_Init(); } 2)编写驱动头文件GUA_Hall_Sensor.h(存放在“……\HARDWARE”) //****************************************************************************** //name: GUA_Hall_Sensor.h //introduce: 霍尔传感器驱动的头文件 //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group 香瓜单片机之STM8/STM32(164311667) //changetime: 2017.03.06 //****************************************************************************** #ifndef _GUA_HALL_SENSOR_H_ #define _GUA_HALL_SENSOR_H_ /*********************宏定义************************/ //类型宏 #ifndef GUA_U8 typedefunsignedchar GUA_U8; #endif #ifndef GUA_8 typedefsignedchar GUA_8; #endif #ifndef GUA_U16 typedefunsignedshort GUA_U16; #endif #ifndef GUA_16 typedefsignedshort GUA_16; #endif #ifndef GUA_U32 typedefunsignedlong GUA_U32; #endif #ifndef GUA_32 typedefsignedlong GUA_32; #endif #ifndef GUA_U64 typedefunsignedlonglong GUA_U64; #endif #ifndef GUA_64 typedefsignedlonglong GUA_64; #endif //霍尔传感器的触发状态 #define GUA_HALL_SENSOR_STATUS_TRIGGER 0 //霍尔传感器触发 #define GUA_HALL_SENSOR_STATUS_IDLE 1 //霍尔传感器没触发 #define GUA_HALL_SENSOR_STATUS_DISAPPERAS_SHAKS 2 //霍尔传感器消抖中 /*********************外部函数声明************************/ GUA_U8 GUA_Hall_Sensor_Check_Pin(void); voidGUA_Hall_Sensor_Init(void); #endif 3)工程中添加GUA_Hall_Sensor.c4)在MDK设置中添加串口驱动源文件路径2、在应用层中调用1)添加驱动头文件(main.c中)#include"GUA_Hall_Sensor.h"2)添加驱动初始化代码(main.c的main函数中)//霍尔传感器初始化GUA_Hall_Sensor_Init(); 3)添加测试代码①写测试代码(main.c中) staticvoidGUA_Test(void) { U8 nGUA_Ret = 0; U8 nGUA_Stop = 0; while(1) { //检测霍尔当前状态 nGUA_Ret = GUA_Hall_Sensor_Check_Pin(); //检测到霍尔被触发 if(nGUA_Ret == GUA_HALL_SENSOR_STATUS_TRIGGER) { nGUA_Stop = 1; } } ②调用测试代码(main.c的main函数中)//测试代码GUA_Test();七、注意事项暂无。八、实验结果仿真并设置断点在测试代码的“nGUA_Stop = 1;”中,全速运行。用磁铁去靠近模块上的霍尔传感器芯片,模块上的led被点亮表示触发,同时工程中消抖之后会停止在断点处,表示检测到PA11处的霍尔传感器触发导致的低电平。如下图因此实验成功。有道云笔记2021-11-16 17:25:02
2025年07月18日
0 阅读
0 评论
0 点赞
2025-07-18
LIN总线详解(2021-11-17)
什么是LIN总线?LIN(Local Interconnect Network)总线是基于UART/SCI(通用异步收发器/串行接口)的低成本串行通讯协议。其目标定位于车身网络模块节点间的低端通信,主要用于智能传感器和执行器的串行通信,而这正是CAN总线的带宽和功能所不要求的部分。CAN/LIN总线区别由于LIN网络在汽车中一般不独立存在,通常会与上层CAN网络相连,形成CAN-LIN网关节点。2.1.LIN总线的主从关系LIN总线采用的是单线传输形式,应用了单主机多从机(有无主动上报的支持?)的概念,总线电平一般为12V,传输速率最高限制为20kbps。由于物理层的限制,一个LIN网络最多可以连接16个节点。总线任务负责:调度总线上帧的传输次序监测数据,处理错误作为标准时钟参考(不是异步通信?)接收从机节点发出的总线唤醒命令从机任务不能直接向总线发送数据,需要接受到主节点发送的帧头后,根据帧头所包含的信息来判断:发送应答接收应答既不接收也不应答LIN的特点网络由一个主节点与若干个从节点构成使用LIN总线可以大幅度削减成本(CAN和Lin都需要收发器,但是Lin属于单线制在线束上节省)传输具有确定性,传播时间可以提前计算LIN具有可预测的EMC(电磁兼容性)性能,为了限制EMC的强度,LIN协议规定最大传输速率为20kbpsLIN总线提供信号的配置、处理、识别和诊断功能(这些都是UART不具备的,可LIN是怎么实现的呢?)3.LIN报文帧结构LIN报文帧包括帧头(hearder)与应答(response)两部分。主机负责发送至帧头;从机负责接收帧头并作出解析,然后决定是发送应答,还是接收应答或不回复。(主机)帧头结构包括同步间隔段、同步段、PID段(受保护ID)段,应答部分包括数据段与效验和段。其中值“0”为显性电平、“1”为隐性电平,这点与CAN总线相类似。在总线上实行“线-与”:当总线有至少一个节点发送显性电平时,总线呈现显性电平;所有节点均发送隐性电平或者不发送信息时,总线呈隐性电平,即显性电平起着主导作用。3.1.1.同步间隔段同步间隔段至少是由13位的显性电平组成,由于帧中的所有间隙或者总线空闲时总线均保持隐性电平状态。所以同步间隔段可以标志一个帧的开始。其中同步间隔段的间隔符至少为1位隐性电平。3.1.2.同步段LIN同步以下降沿为判断标志,采用字节0x55(01010101b)进行同步。在从机节点上可以不采用高精度的时钟,由此带来的偏差,需要通过同步段来进行调整。3.1.3.PID段受保护的ID的前6位叫做帧ID,加上两个奇偶效验码后称作受保护的ID。帧ID的取值范围为0x00~0x3f总共64个,帧ID标识了帧的类别和目的地。从机任务会根据帧头ID作出反应(接收/发送/忽略应答)。其中P0与P1效验如下:LIN总线根据帧ID号的不同,把报文分为信号携带帧、诊断帧、保留帧。PS:从机应答帧是一个完整的帧,与(主节点)帧结构中的“应答”不同!3.1.4.数据段数据段可以包含1-8个字节,其中包含有两种数据类型,信号(singal)和诊断消息(diagnostic messages)。信号由信号携带帧传递,诊断消息由诊断帧传递。协议中并没有规定哪一部分显示数据长度码的信息(这点与CAN总线不同),数据的内容与长度均是由系统设计者根据帧ID事先约定好的。总线上的数据是以广播形式发出,任何节点均可以收到,但并非对每个节点有用(与CAN相同)。具体到发布与接听是由哪个节点进行完成这个取决于应用层的软件配置,一般情况下,对于一个帧中的应答,总线上只存在一个发布节点,否则就会出现错误。事件触发帧例外,可能出现0,1,多个发布节点。3.1.5.效验和段效验和段是为了对帧传输内容进行效验。效验分为标准型效验与增强型效验。采用标准型还是增强型是由主机节点管理,发布节点和收听节点根据帧ID来判断采用哪种效验和。4.LIN总线波形5.LIN总线的通讯上图展示的是LIN总线的通讯方式,可以看出无论什么时候帧头总是由主机节点发布,当主机节点想发布数据时,整个帧全部由主机节点发送。当从机节点想发布数据时,帧头部分由主机节点发布,应答部分由从机节点发布(主机怎么知道从机节点想发布数据,那肯定是主机节点无数据可发,故只发了帧头?),这样其余节点都能收到一个完整的报文帧。可以很直接的观察到,LIN总线的通讯都是由主机节点发起的,只要合理的规定要每个节点的配置,这样就不会存在总线冲突的情况(事件触发帧冲突时采用采用冲突解决进度表)。帧类型5.1.无条件帧无条件帧是具有单一发布节点的,无论信号是否发生变化,帧头均会被无条件应答的帧。如上图中帧ID=0x30应答部分的发布节点为从机节点1,收听节点为主机节点,应用在从机节点向主机节点报告自身状态;帧ID=0x31中,应答部分为主机节点,收听部分为从机节点,应用在主机节点向从机节点发送消息;帧ID=0x32中应答部分的发送节点为从机节点2,收听节点为从机节点1,应用与从机节点之间的通信。5.2.事件触发帧事件触发帧是主机节点在一个帧间隙中查询各从机节点的信号是否发生变化时使用的帧。当存在多个发布节点时,通过冲突解决进度表来解决冲突。当从机节点信号发生变化的频率较低的时候,主机任务一次次地查询各个节点信息会占用一定的带宽。为了减小带宽的占用,引入了事件触发帧的概念。其主要原理就是:当从机节点信息状态没有发生变化的时候,从机节点可以不应答主机发出的帧头;当有多个节点信息同时发生变化的时候,同时应答事件触发帧头会造成总线的冲突。当主机节点检测到冲突时,便会查询冲突解决进度表来依次向各个节点发送无条件帧(无条件帧只有能1个节点应答)来确定从机节点的信息状态。与事件触发帧关联的多个无条件帧需要满足以下5个条件:数据段所包含的数据字节数等长 使用相同的效验与类型 数据段的第一个字节为该无条件帧的受保护ID,这样才能够知道应答是哪个关联的无条件帧发送出来的 由不同的从机节点发布 不能与时间触发帧处于同一个进度表中5.2.1.偶发帧偶发帧是主机节点在同一帧时隙中当自身信号发生变化时向总线启动发送的帧。当存在多个关联的应答信号变化时,通过预先设定的的优先级来仲裁。与事件触发帧类似,偶发帧也定义了一组无条件帧。规定偶发帧只有由主机节点发布。偶发帧的传输可能出现三种情况:当关联的无条件帧没有信号发生变化,这是主机连帧头也不需要发送。当关联的一个无条件帧信号发生变化则发送该帧。当有多个无条件帧发生信号变化时,则按照事先规定要的优先级依次发送。5.2.2.诊断帧诊断帧包括主机请求帧和从机应答帧,主要用于配置、识别和诊断。主机请求帧ID=0x3c,应答部分的发布节点为主机节点;从机应答帧ID=0x3d,应答部分的发布节点为从机节点。数据段规定为8个字节,一律采用标准效验和。5.2.3.保留帧保留帧的ID=0x3e与0x3f,为将来扩张需求用。5.3.进度表进度表是帧的调度表,规定了总线上帧的传输次序以及传输时间。进度表位于主机节点,主机任务根据应用程需要进行调度。进度表可以有多个,一般情况下,轮到某个进度表执行的时候,从该进度表的入口处开始执行,到进度表的最后一个帧时,如果没有新的进度表启动则返回到当前进度表的第一个帧开始执行;也有可能在执行到某个进度表时发生中断,跳到另一个进度表后再返回,如事件触发帧就是一个典型的例子。6.状态机的实现6.1.主机状态机6.2.从机状态机从机任务负责发布或者接听帧的应答状态,包括连两个状态机:同步间隔段与同步段检查器、帧处理器。6.3.从机任务状态机6.4.帧处理任务状态机有道云笔记2021-11-17 15:22:32
2025年07月18日
0 阅读
0 评论
0 点赞
2025-07-17
KEIL5 仿真 —— 示波器显示(2021-11-18)
记录一下如何使用 KEIL5 的示波器查看变量波形。这里先列出我参考的资料:你知道 KEIL 自带示波器吗?STM32:keil的软件逻辑分析仪( logic analyzer)使用调节项目的 Xtal 为 8KHzDebug 出选择 "Use Simulator","Dialog DLL" 和 "Parameter" 也需要更改,软件仿真填入 "DARMSTM.DLL" ,参数为 "-pSTM32F103VE",这里是我的STM32芯片型号。硬件仿真填入 "TARMSTM.DLL" 。然后点击仿真按钮开始仿真。打开逻辑分析仪窗口。点击 View 菜单,选择 "Symbols Window" 选项,在弹出的窗口里 "Special Function Register" 里找到查看波形的引脚。这里比如 GPIOB_IDR,按住后将其拖入逻辑分析仪窗口。点击 "Setup",将 "Display Type" 选为 "Bit",且用 "And Mask" 和 "Shift Right" 来过滤掉不需要显示的位。关闭,全速运行,即可看见指定引脚的波形。有道云笔记2021-11-18
2025年07月17日
2 阅读
0 评论
0 点赞
2025-07-17
timer的输入捕获功能(2021-11-18 )
内部定时器结构在 STM32定时器系列 - STM32常规定时器时基与时钟源 这篇博文中,我们讲述过,定时器的结构。其实我们只需要看这张图就可以了:看流程的走向,由 时钟源 提供时钟 到 时间基(一般时钟源都是选择内部的CLK)这里需要注意的就是看定时器时挂在那个总线下的,APB1 与 APB2 CLK不一样。然后流向 输入捕获 的只有 PSC(预分配器) 并没有 重装载寄存器,因此,采样的频率就是定时器经过预分配器之后的频率,与重装载无关。输入捕获【Input Capture】基本原理定时器针对外部输入信号或者内部触发信号实现"边沿捕获";产生捕捉事件,并可以触发中断或者DMA请求,同时记录捕捉时刻计数器的值,基于这个原理,配合计数器实时计数器功能可以对捕捉信号进行脉冲宽度的测量,进而实现对周期性波形测量其周期与占空比,或者用来做通信解码(红外通信解码)。具体到我们的定时器,输入捕获的功能主要是靠捕获比较单元来实现。输入捕获模式下:当捕获单元捕获到外来有效信号边沿事件【上升沿或者下降沿】,将此刻计数器的值锁存到CCR影子寄存器并自动将CCR影子寄存器的值拷贝进CCR预装寄存器,以供用户读取。关于CCR寄存器,它是由影子寄存器与预装寄存器组成,带预装使能控制位。在输入模式下,此时CCR对用户是只读的,不可对其修改、赋值。外部输入信号作为输入捕获信号,往往需要经过如下几个阶段:一般经过滤波,边沿检测,极性选择,捕获信号选择,捕获信号分频,最终进入捕获功能模块从而实现输入捕获。其中边沿检测、极性选择确定捕获单元对捕获信号的捕获极性,即捕获上升沿还是下降沿,甚至双边沿。捕获信号选择是指:对输入捕获信号的信号进行选择,即前面提到过的作为捕获信号的信号源有两大类;捕获信号分频是指对将被用作捕获信号的信号进行分频,比如2分频,3分频等,分频之后送到捕获功能模块去完成输入捕获。(这里如果输入信号频率大于采样频率就可以采用捕获信号分频的方法降低信号频率,达到可以采集的目标,计算结果后,在乘以分频系数)外部输入信号的滤波为了防止因为输入信号上的噪声或边沿抖动而导致误计数、误触发,我们可以针对外部输入信号进行合适的滤波。用户要做的就是针对输入信号具体情况【频率、噪声等】,通过寄存器配置适当的滤波参数,选择适当采样时钟和采样次数,其它事情交给定时器硬件去处理。这样也可以减少因为做滤波而导致的软件开销。假设我们让定时器对某输入通道的信号进行捕捉,捕捉极性为上升沿。设置滤波的采样时钟与定时器内部时钟频率一致,采样次数为4次。则每当捕捉到上升沿时,硬件连续根据采样频率来采样4次【包括发生捕捉触发沿的那一次】。如果4次采样结果均为高电平,则此次触发有效。并可以产生触发事件,该事件可以触发中断或DMA请求,同时捕捉单元将此刻计数器的值放入到捕捉比较寄存器CCR中。当然,如果捕捉到触发边沿后,没法做到连续4次采样均为高电平,则该触发无效,将会被丢弃。这样达到滤除噪声的目的。内部触发输入信号【ITRx】作为输入捕获信号与输入捕获相关的事件捕获时刻的计数器值锁存到对应捕获通道的CCRx寄存器。对应通道的捕获事件/中断会被置位;【CCxIF@TIMx_SR】如果允许了捕获中断或者DMA请求,可以触发中断或者DMA请求。取决于【CCxIE/CCxDE@TIMx_DIER】配置。如果运行连续捕获事件,前一次没有清零的话会置位【CCxOF@TIMx_SR】对于CCxIF标志可以软件清零或者读取CCR来清零。可以通过设置位【CCxG@TIMx_EGR】来软件触发输入捕获事件。与输入捕获相关的事件主要就这些,我们要做到心中有数。只要了解它们后,在我们的定时器的实际应用中才能灵活使用它们,实现我们需要的功能。如在发生输入捕获事件时,利用相关中断或DMA请求实现其它功能,比如做数据的更新、ADC的启动、其它定时器的启动等等。通过输入捕获测量脉冲周期在输入捕捉模式下,定时器可用于测量外部信号周期。根据定时器时钟、预分频器和定时器分辨率,可推导出最大测量周期。相应的定时器配置包括:通过对CCMRx 寄存器中的 CCxS 位选择有效输入。根据需要,通过对 CCMRx 寄存器中的 IC1F[3:0] 位执行操作以编程滤波器参数,并通过对IC1PSC[1:0] 位执行写操作以编程预分频器。通过对 CCxNP/CCxP 位执行写操作选择极性,即选择上升沿触发、下降沿触发或边沿触发。当输入通道检测到相应的信号发生跳变时,可使用输入捕捉模块进行捕捉。要获取外部信号周期,需连续进行两次捕捉,通过将两次捕捉到的值相减可计算得到周期。对于单沿捕捉,计数器采用向上计数模式,待测信号不长于计数器的计数周期时:假设两次连续捕捉值为 CCRx_tn 和 CCRx_tn+1● 如果 CCRx_tn < CCRx_tn+1:捕捉宽度= CCRx_tn+1 - CCRx_tn● 如果 CCRx_tn > CCRx_tn+1:捕捉宽度= (ARR_max - CCRx_tn) + CCRx_tn+1如果待测信号周期长于当前计数器周期的话,需要考虑溢出问题。实际应用中有时因为忽略了这点而导致测试不正确。有道云笔记2021-11-18 17:40:28
2025年07月17日
0 阅读
0 评论
0 点赞
1
2
3