皮皮网
皮皮网

【同城微社区源码】【新版暗雷 源码】【zao 换脸 源码】vpp源码阅读

来源:springboot面试及源码 发表时间:2024-11-30 12:53:31

1.关于vpp中dpdk接口注册流程解析
2.技术干货!码阅DPDK新手入门到网络功能深入理解
3.关于VPP源码——dpo机制源码分析
4.AddressSanitizer,码阅增强DPDK内存检测
5.VPP 编译、码阅安装、码阅使用及插件开发注意事项
6.DPDK-VPP 学习笔记-01

vpp源码阅读

关于vpp中dpdk接口注册流程解析

       vpp 是码阅一个高效的包处理转发框架,支持多种接口类型,码阅同城微社区源码其中应用最广泛的码阅便是 dpdk。dpdk 通过接管网卡驱动实现内核旁路,码阅提供报文收发加速机制。码阅在 vpp 中,码阅dpdk 作为插件实现,码阅通过 make install-ext-deps 构建过程中自动集成 dpdk。码阅

       dpdk 初始化在 /src/plugins/dpdk/device/init.c 文件中,码阅dpdk 的码阅 eal 环境通过调用 rte_eal_init 函数实现。dpdk_config 函数负责参数解析,码阅dpdk_config 函数通过宏 VLIB_CONFIG_FUNCTION 注入,vpp 启动时自动调用,将参数传递给 rte_eal_init 进行初始化。

       vpp 的接口层分为硬件层和软件层,硬件层通过 device class 描述硬件驱动,软件层通过 interface class 描述链路层。硬件设备用 vnet_hw_interface_t 结构体描述,软件层接口用 vnet_sw_interface_t 描述。接口统一管理在 vnet_interface_main_t 结构体中,该结构体定义了硬件接口和软件接口的数组。

       接口初始化在 vnet_interface_init 函数中进行,此函数除了初始化接口参数,还会将 dpdk 设备的 tx_function 赋值给 device class,决定后续的发包执行函数。

       dpdk 接口初始化在 dpdk_lib_init 函数中完成,主要步骤包括初始化 dpdk_device_t 结构体,调用 ethernet_register_interface 注册接口,配置网卡参数,并为接口分配收包线程。

       dpdk 收包通过 input node dpdk_input_node 实现,dpdk_device_input 函数完成实际的收包操作,通常将报文传递给下一个 node,如 ethernet_input node。

       dpdk 发包逻辑相对复杂,dpdk 的发包并未直接在插件中实现专门的 output node,而是通过接口 tx_function 赋值,最终在 vpp 的发送流程中实现。在发送报文时,接口的 output node 和 tx node 会在 vnet_register_interface 注册接口时一同注册,其中 output node 的执行函数是 vnet_interface_output_node,tx node 的函数则由 vnet_device_class_t 定义。

       发送流程以 ip4 报文为例,处理完 ip4 报文后,通常下一个节点为 ip4-lookup 进行路由查找。在 interface-output node 中,通过 buffer->sw_if_index[VNET_TX] 的值确定发送接口,并执行对应的 output node。

       在 interface output node 的执行函数中,接口的 output node index 通过调用 vnet_per_buffer_interface_output_hw_interface_add_del 函数获得,该函数在 vpp 初始化过程中将接口的 output node 放置在 interface output node 后面,从而在执行函数中获取到接口 output node 的索引。

       vpp 的设计遵循分层架构,逻辑清晰,但宏定义的大量使用增加了阅读难度。 版本源码调整了 node 注册方式,通过 VLIB_NODE_FN 宏实现不同优先级的 function 设置,但这一改动也给源码阅读带来不便。接口发送节点通过 vlib_register_node 函数定义,允许不同驱动共享一个函数,方便了接口的动态添加。

       vpp 启动过程中的宏定义执行顺序影响代码结构,后续深入阅读源码时会进一步分析。如有需要,可参考相关学习资料、教学视频和交流群资源进行深入学习和交流。

技术干货!DPDK新手入门到网络功能深入理解

       DPDK新手入门

       一、安装

       1. 下载源码

       DPDK源文件由几个目录组成。

       2. 编译

       二、配置

       1. 预留大页

       2. 加载 UIO 驱动

       三、运行 Demo

       DPDK在examples文件下预置了一系列示例代码,这里以Helloworld为例进行编译。

       编译完成后会在build目录下生成一个可执行文件,通过附加一些EAL参数可以运行起来。

       以下参数都是新版暗雷 源码比较常用的

       四、核心组件

       DPDK整套架构是基于以下四个核心组件设计而成的

       1. 环形缓冲区管理(librte_ring)

       一个无锁的多生产者,多消费者的FIFO表处理接口,可用于不同核之间或是逻辑核上处理单元之间的通信。

       2. 内存池管理(librte_mempool)

       主要职责是在内存中分配用来存储对象的pool。 每个pool以名称来唯一标识,并且使用一个ring来存储空闲的对象节点。 它还提供了一些其他的服务,如针对每个处理器核心的缓存或者一个能通过添加padding来使对象均匀分散在所有内存通道的对齐辅助工具。

       3. 网络报文缓冲区管理(librte_mbuf)

       它提供了创建、释放报文缓存的能力,DPDK应用程序可能使用这些报文缓存来存储数据包。这个缓存通常在程序开始时通过DPDK的mempool库创建。这个库提供了创建和释放mbuf的API,能用来暂存数据包。

       4. 定时器管理(librte_timer)

       这个模块为DPDK的执行单元提供了异步执行函数的能力,也能够周期性的触发函数。它是通过环境抽象层EAL提供的能力来获取的精准时间。

       五、环境抽象层(EAL)

       EAL是用于为DPDK程序提供底层驱动能力抽象的,它使DPDK程序不需要关注下层具体的网卡或者操作系统,而只需要利用EAL提供的抽象接口即可,EAL会负责将其转换为对应的API。

       六、通用流rte_flow

       rte_flow提供了一种通用的方式来配置硬件以匹配特定的Ingress或Egress流量,根据用户的任何配置规则对其进行操作或查询相关计数器。

       这种通用的方式细化后就是一系列的流规则,每条流规则由多种匹配模式和动作列表组成。

       一个流规则可以具有几个不同的动作(如在将数据重定向到特定队列之前执行计数,封装,解封装等操作),而不是依靠几个规则来实现这些动作,应用程序操作具体的硬件实现细节来顺序执行。

       1. 属性rte_flow_attr

       a. 组group

       流规则可以通过为其分配一个公共的组号来分组,通过jump的流量将执行这一组的操作。较低的值具有较高的优先级。组0具有最高优先级,且只有组0的规则会被默认匹配到。

       b. 优先级priority

       可以将优先级分配给流规则。像Group一样,较低的值表示较高的优先级,0为最大值。

       组和优先级是任意的,取决于应用程序,它们不需要是连续的,也不需要从0开始,但是最大数量因设备而异,并且可能受到现有流规则的影响。

       c. 流量方向ingress or egress

       流量规则可以应用于入站和/或出站流量(Ingress/Egress)。

       2. 模式条目rte_flow_item

       模式条目类似于一套正则匹配规则,用来匹配目标数据包,其结构如代码所示。

       首先模式条目rte_flow_item_type可以分成两类:

       同时每个条目可以最多设置三个相同类型的结构:

       a. ANY可以匹配任何协议,还可以一个条目匹配多层协议。

       b. ETH

       c. IPv4

       d. TCP

       3. 操作rte_flow_action

       操作用于对已经匹配到的数据包进行处理,同时多个操作也可以进行组合以实现一个流水线处理。

       首先操作类别可以分成三类:

       a. MARK对流量进行标记,会设置PKT_RX_FDIR和PKT_RX_FDIR_ID两个FLAG,具体的值可以通过hash.fdir.hi获得。

       b. QUEUE将流量上送到某个队列中

       c. DROP将数据包丢弃

       d. COUNT对数据包进行计数,如果同一个flow里有多个count操作,则每个都需要指定一个独立的id,shared标记的计数器可以用于统一端口的不同的flow一同进行计数。

       e. RAW_DECAP用来对匹配到的数据包进行拆包,一般用于隧道流量的剥离。在action定义的时候需要传入一个data用来指定匹配规则和需要移除的内容。

       f. RSS对流量进行负载均衡的操作,他将根据提供的数据包进行哈希操作,并将其移动到对应的队列中。

       其中的level属性用来指定使用第几层协议进行哈希:

       g. 拆包Decap

       h. One\Two Port Hairpin

       七、常用API

       1. 程序初始化

       2. 端口初始化

       3. 队列初始化

       DPDK-网络协议栈-vpp-ovs-DDoS-虚拟化技术

       DPDK技术路线视频教程地址立即学习

       一、DPDK网络

       1. 网络协议栈项目

       2.dpdk组件项目

       3.dpdk经典项目

       二、DPDK框架

       1. 可扩展的矢量数据包处理框架vpp(c/c++)

       2.DPDK的虚拟交换机框架OvS

       3.golang的网络开发框架nff-go(golang)

       4. 轻量级的switch框架snabb(lua)

       5. 高效磁盘io读写spdk(c)

       三、DPDK源码

       1. 内核驱动

       2. 内存

       3. 协议

       4. 虚拟化

       5. cpu

       6. 安全

       四、性能测试

       1. 性能指标

       2. 测试方法

       3. 测试工具DPDK相关学习资料分享:点击领取,备注DPDK

       DPDK新手入门原文链接:DPDK上手

关于VPP源码——dpo机制源码分析

       VPP的dpo机制紧密与路由结合。路由查找的最终结果为load_balance_t结构,相当于一个hash表,包含多种dpo,指向下一步动作。zao 换脸 源码dpo标准类型包括:DPO_LOAD_BALANCE、DPO_DROP、DPO_IP_NULL、DPO_PUNT。DPO_LOAD_BALANCE内含私有数据load_balance_t,通过dpo_id_t中的dpoi_index索引具体实例。DPO_DROP将数据包送往"XXX-drop"节点,简单处理后传至"error-drop"节点完成数据包丢弃。DPO_IP_NULL将数据包送往"ipx-null"节点,决定是否回传icmp不可达或禁止包。

       DPO_PUNT与DPO_PUNT核心函数与加锁/解锁无关。这些函数增加私有数据结构的引用计数,对于无私有数据的dpo则为空实现。内部调用注册时提供的函数指针。dpo设置操作包括将数据包从child dpo传递给parent dpo。通过在child dpo的dpoi_next_node中增加指向parent dpo对应node的slot索引,实现数据包传递。dpo_edges为四重指针,用于缓存child dpo对应的node指向下一跳parent dpo对应node的slot索引。

AddressSanitizer,增强DPDK内存检测

       前言

       在使用C/C++构建程序时,内存问题常成为难题,难以复现和定位。这类问题主要源于内存越界和重复释放。内存管理机制存在不足,DPDK内存检测仅在rte_free时进行,调试信息有限。市面上虽有多种内存管理工具,但缺乏DPDK适用且高效的解决方案。

       内存检测机制

       多数内存检测工具通过建立红区(redzones)来实现检测。红区环绕进程内存的绿色区域,通过影子内存记录访问状态。影子内存需一大块连续虚拟地址空间,供快速查找访问权限,并在每次内存访问前通过代码插桩检查影子区域状态。

       动态库实时检测影子内存状态,允许或阻止内存访问,生成诊断报告。ASan工具采用高效映射机制,使用紧凑影子编码,减少影子内存占用。

       相关视频推荐

       深入了解VPP源码流程、动态库加载、插件、节点和特性。

       高性能网络开发框架VPP与DPDK解决了网卡问题。

       NFV基石DPDK,为网络定义新功能。

       免费学习资源:DPDK、网络协议栈、VPP、OvS、DDoS、NFV、虚拟化、高性能专家。

       DPDK学习路线:0voice.com/uiwebsite/ht...

       文章福利:提供学习书籍、视频资料,自行加入(需要自取)。

       AddressSanitizer原理及在DPDK中实现

       AddressSanitizer(ASan)是Google开发的内存检测工具,通过高效映射和紧凑编码方法优化效率。ASan使用1/8虚拟地址空间的影子内存描述所有地址,构建高效查找机制,通过原始指针除以8和偏移量计算影子内存位置。

       插桩技术在内存访问前进行检查,替换glibc函数进行实时检测,设置红区标记内存不可访问。Free函数将内存染毒并隔离。日志记录调用栈,快速定位问题。ASan使用启发法关联错误地址,记录和报告错误信息。

       ASan在DPDK中的实现

       ASan基于glibc实现,但DPDK内存管理方式不同,导致动态运行库无法直接挂载。GCC和CLANG支持ASan编译选项,通过在malloc和free函数中实现设置红区。已将ASan代码合并至DPDK .,详情可下载代码查看。曲多多网站源码

       如何在DPDK中启用ASan工具检测内存

       Meson编译DPDK代码时,添加“-Db_sanitize=address”启用ASan。GCC编译时可不加“-Db_lundef=false”选项,使用“-Dbuildtype=debug”选项输出更多日志信息。推荐使用上述编译选项。

       ASan支持检测缓存溢出、释放后使用等内存问题。检测信息包含文件、行、函数调用过程,便于高效定位问题。

       启用ASan工具后,会带来一定性能下降和内存开销,适用于代码调试和集成测试阶段。Intel DPDK测试部门已部署ASan工具,发现并修复多个静态工具无法检测的内存问题。CI系统也将ASan检测纳入DPDK代码测试。

VPP 编译、安装、使用及插件开发注意事项

       VPP(Vector Packet Processing)是一个由Cisco开发的开源可扩展框架,用于提供易于使用的高性能交换和路由功能。它通过使用各种插件(Plugin)来处理网络协议,这些插件可以在配置代码中指定其后续操作。插件间的处理逻辑通过返回的索引链接起来,形成一个处理流程。

       VPP的核心在于其高性能处理机制,它将相同类型的包放在数组中,利用CPU缓存提高效率,并通过SSE、AVX指令加速(x平台)、NEON指令加速(ARM平台)或AltiVec技术加速(PowerPC平台)。Bihash实现了一个高效的检索表结构,支持读写分离。

       VPP安装非常简单,无需编译步骤,直接从官方网站下载源代码,通过apt/yum更新后,执行apt/yum install vpp即可完成安装。不过需要注意的是,安装的版本可能较低。

       在使用VPP时,新版本内置了DPDK,但默认情况下未启用高性能模式。默认运行方式可能为socket/af_packet,性能一般。如果你熟悉交换机指令,VPP的使用方式会很熟悉,具有自动补全、帮助和显示信息的功能。创建虚拟网口与VPP建立通信通常使用veth技术。

       创建虚拟网口时,如需让VPP运行,通常需要通过命令创建网口并开启主机到VPP的通道。具体操作可参考以下示例:创建虚拟网口与VPP内部建立通讯。

       VPP提供了一套完整的命令系统,允许用户进行详细的配置和调试。使用VPP指令时,通过ping .0.0.2检查网络连通性,同时VPP内部的show int命令可以显示统计数据的变化情况,而主机通过tcpdump工具可以抓取到包。

       编写插件时,可以参考src/examples/sample_plugin/sample中的示例代码。插件初始化代码在sample.c/sample_init函数中,其中VNET_FEATURE_INIT宏定义了前导节点及插入到哪个节点前面。默认位置为ethernet-input,即适配器输入的前面。vnet_feature_enable_disable函数用于激活节点,参数1通常包含前一步中定义的值。在插件命令执行时,如sample macswap,将调用相应的节点逻辑。

       丢包操作可以通过在插件初始化时获取error_drop节点的全局索引,然后将需要丢弃的包存储到目标位置,并使用vlib_put_frame_to_node函数将包放入error_drop节点。实现时,可以使用vlib_get_next_frame获取目标包地址,然后使用put_frame函数将包放入指定位置。

       编写和编译插件的流程相对标准,使用emacs进行编辑。大灰狼源码3.0VPP的源码编译相对简单,通常只需执行几条命令即可。需要注意的是,在编译过程中,可能会遇到如内存分配不足等问题,因此在虚拟机环境和图形界面下需进行相应的优化。同时,在特定版本和环境下,可能需要额外的依赖库和配置文件。

       在安装和配置VPP时,可能会遇到一些常见的问题,例如无法打开日志文件、组vpp不存在等。这些问题通常可以通过调整配置文件或创建相关目录来解决。在某些版本和环境下,安装时可能需要额外的依赖包,如intel-ipsec-mb、dpdk、rdma-core、xdp-tools、quicly、meson等,确保在编译和安装过程中正确配置这些依赖。

       最后,确保在安装和运行VPP时有足够的磁盘空间,特别是在配置DPDK时,需要充足的内存资源。如果在HyperV下的Ubuntu.环境中遇到问题,可能需要额外的配置和优化。对于较新的Ubuntu版本,确保使用的是适合VPP版本的系统软件包,避免因版本不兼容导致的问题。

DPDK-VPP 学习笔记-

       原文链接: blog.csdn.net/force_eag...

       安装方法:

       借助CentOS使用yum安装vpp-debuginfo和vpp-devel,可选。

       源码安装:直接通过git clone至本地或下载指定版本源码。采用git clone方式和版本v..1,执行make install-dep自动下载所需dpdk版本和依赖库。

       编译流程:

       编译vpp需注意:源码解压后无法编译rpm和deb安装包。需在编译前清除vpp。

       关键编译参数:查看build-data/platforms/vpp.mk与build/external/packages/dpdk.mk中的Makefile源代码,注意指定dpdk pmd mlx5支持。

       vpp使用指南:

       确认系统网卡型号,重新绑定至igb_uio驱动。

       初始化hugepages大小,推荐使用默认的2M页面,分配M。

       启动与操作:

       启动vpp。

       vppctl常用命令示例:针对具体接口名称(如GigabitEthernet5/0/0或TenGigabitEthernet5/0/0)。

       配置文件与学习资源:

       参考:FD.io VPP v..1,高性能网络开发框架,提升技术层次。

       深入学习资料、教学视频和学习路线图,涵盖dpdk、网络协议栈、vpp、OvS、DDos、NFV、虚拟化、高性能等内容,免费分享至学习交流群。

ATC和ATS的区别?

       ATC是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。ATC是一种带2K字节闪烁可编程可擦除只读存储器的单片机。单片机的可擦除只读存储器可以反复擦除次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的ATC是一种高效微控制器,ATC是它的一种精简版本。ATC单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。外形及引脚排列如图所示

       [编辑本段]主要特性:

         ·与MCS- 兼容 

         ·4K字节可编程闪烁存储器 

         ·寿命:写/擦循环

         ·数据保留时间:年

         ·全静态工作:0Hz-MHz

         ·三级程序存储器锁定

         ·×8位内部RAM

         ·可编程I/O线

         ·两个位定时器/计数器

         ·5个中断源 

         ·可编程串行通道

         ·低功耗的闲置和掉电模式

         ·片内振荡器和时钟电路

       管脚说明:

         VCC:供电电压。

         GND:接地。

         P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

         P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。 

         P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

         P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

         P3口也可作为ATC的一些特殊功能口,如下表所示:

         口管脚 备选功能

         P3.0 RXD(串行输入口)

         P3.1 TXD(串行输出口)

         P3.2 /INT0(外部中断0)

         P3.3 /INT1(外部中断1)

         P3.4 T0(记时器0外部输入)

         P3.5 T1(记时器1外部输入)

         P3.6 /WR(外部数据存储器写选通)

         P3.7 /RD(外部数据存储器读选通)

         P3口同时为闪烁编程和编程校验接收一些控制信号。

         RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

         ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

         /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

         /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加V编程电源(VPP)。

         XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

         XTAL2:来自反向振荡器的输出。

         振荡器特性:

         XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片内振荡器。石晶振荡和陶瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。

       芯片擦除:

         整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平ms 来完成。在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。

         此外,ATC设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。在闲置模式下,CPU停止工作。但RAM,定时器,计数器,串口和中断系统仍在工作。在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止。 

         串口通讯

         单片机的结构和特殊寄存器,这是你编写软件的关键。至于串口通信需要用到那些特殊功能寄存器呢,它们是SCON,TCON,TMOD,SCON等,各代表什么含义呢?

         SBUF 数据缓冲寄存器这是一个可以直接寻址的串行口专用寄存器。有朋友这样问起过“为何在串行口收发中,都只是使用到同一个寄存器SBUF?而不是收发各用一个寄存器。”实际上SBUF 包含了两个独立的寄存器,一个是发送寄存,另一个是接收寄存器,但它们都共同使用同一个寻址地址-H。CPU 在读SBUF 时会指到接收寄存器,在写时会指到发送寄存器,而且接收寄存器是双缓冲寄存器,这样可以避免接收中断没有及时的被响应,数据没有被取走,下一帧数据已到来,而造成的数据重叠问题。发送器则不需要用到双缓冲,一般情况下我们在写发送程序时也不必用到发送中断去外理发送数据。操作SBUF寄存器的方法则很简单,只要把这个H 地址用关键字sfr定义为一个变量就可以对其进行读写操作了,如sfr SBUF = 0x;当然你也可以用其它的名称。通常在标准的reg.h 或atx.h 等头文件中已对其做了定义,只要用#include 引用就可以了。

         SCON 串行口控制寄存器通常在芯片或设备中为了监视或控制接口状态,都会引用到接口控制寄存器。SCON 就是 芯片的串行口控制寄存器。它的寻址地址是H,是一个可以位寻址的寄存器,作用就是监视和控制 芯片串行口的工作状态。 芯片的串口可以工作在几个不同的工作模式下,其工作模式的设置就是使用SCON 寄存器。它的各个位的具体定义如下:

         SM0 SM1 SM2 REN TB8 RB8 TI RI

         SM0、SM1 为串行口工作模式设置位,这样两位可以对应进行四种模式的设置。串行口工作模式设置。

         SM0 SM1 模式 功能 波特率

         0 0 0 同步移位寄存器 fosc/

         0 1 1 8位UART 可变

         1 0 2 9位UART fosc/ 或fosc/

         1 1 3 9位UART 可变

         在这里只说明最常用的模式1,其它的模式也就一一略过,有兴趣的朋友可以找相关的硬件资料查看。表中的fosc 代表振荡器的频率,也就是晶振的频率。UART 为(Universal Asynchronous Receiver)的英文缩写。

         SM2 在模式2、模式3 中为多处理机通信使能位。在模式0 中要求该位为0。

         REM 为允许接收位,REM 置1 时串口允许接收,置0 时禁止接收。REM 是由软件置位或清零。如果在一个电路中接收和发送引脚P3.0,P3.1 都和上位机相连,在软件上有串口中断处理程序,当要求在处理某个子程序时不允许串口被上位机来的控制字符产生中断,那么可以在这个子程序的开始处加入REM=0 来禁止接收,在子程序结束处加入REM=1 再次打开串口接收。大家也可以用上面的实际源码加入REM=0 来进行实验。

         TB8 发送数据位8,在模式2 和3 是要发送的第9 位。该位可以用软件根据需要置位或清除,通常这位在通信协议中做奇偶位,在多处理机通信中这一位则用于表示是地址帧还是数据帧。

         RB8 接收数据位8,在模式2 和3 是已接收数据的第9 位。该位可能是奇偶位,地址/数据标识位。在模式0 中,RB8 为保留位没有被使用。在模式1 中,当SM2=0,RB8 是已接收数据的停止位。

         TI 发送中断标识位。在模式0,发送完第8 位数据时,由硬件置位。其它模式中则是在发送停止位之初,由硬件置位。TI 置位后,申请中断,CPU 响应中断后,发送下一帧数据。在任何模式下,TI 都必须由软件来清除,也就是说在数据写入到SBUF 后,硬件发送数据,中断响应(如中断打开),这时TI=1,表明发送已完成,TI 不会由硬件清除,所以这时必须用软件对其清零。

         RI 接收中断标识位。在模式0,接收第8 位结束时,由硬件置位。其它模式中则是在接收停止位的半中间,由硬件置位。RI=1,申请中断,要求CPU 取走数据。但在模式1 中,SM2=1时,当未收到有效的停止位,则不会对RI 置位。同样RI 也必须要靠软件清除。常用的串口模式1 是传输 个位的,1 位起始位为0,8 位数据位,低位在先,1 位停止位为1。它的波特率是可变的,其速率是取决于定时器1 或定时器2 的定时值(溢出速率)。ATC 和ATC 等 系列芯片只有两个定时器,定时器0 和定时器1,而定时器2是C 系列芯片才有的。

         波特率在使用串口做通讯时,一个很重要的参数就是波特率,只有上下位机的波特率一样时才可以进行正常通讯。波特率是指串行端口每秒内可以传输的波特位数。有一些初学的朋友认为波特率是指每秒传输的字节数,如标准 会被误认为每秒种可以传送个字节,而实际上它是指每秒可以传送 个二进位,而一个字节要8 个二进位,如用串口模式1 来传输那么加上起始位和停止位,每个数据字节就要占用 个二进位, 波特率用模式1 传输时,每秒传输的字节数是÷= 字节。 芯片的串口工作模式0的波特率是固定的,为fosc/,以一个M 的晶振来计算,那么它的波特率可以达到1M。模式2 的波特率是固定在fosc/ 或fosc/,具体用那一种就取决于PCON 寄存器中的SMOD位,如SMOD 为0,波特率为focs/,SMOD 为1,波特率为focs/。模式1 和模式3 的波特率是可变的,取决于定时器1 或2( 芯片)的溢出速率。那么我们怎么去计算这两个模

         式的波特率设置时相关的寄存器的值呢?可以用以下的公式去计算。

         波特率=(2SMOD÷)×定时器1 溢出速率

         上式中如设置了PCON 寄存器中的SMOD 位为1 时就可以把波特率提升2 倍。通常会使用定时器1 工作在定时器工作模式2 下,这时定时值中的TL1 做为计数,TH1 做为自动重装值 ,这个定时模式下,定时器溢出后,TH1 的值会自动装载到TL1,再次开始计数,这样可以不用软件去干预,使得定时更准确。在这个定时模式2 下定时器1 溢出速率的计算公式如下:

         溢出速率=(计数速率)/(-TH1)

         上式中的“计数速率”与所使用的晶体振荡器频率有关,在 芯片中定时器启动后会在每一个机器周期使定时寄存器TH 的值增加一,一个机器周期等于十二个振荡周期,所以可以得知 芯片的计数速率为晶体振荡器频率的1/,一个M 的晶振用在 芯片上,那么 的计数速率就为1M。通常用.M 晶体是为了得到标准的无误差的波特率,那么为何呢?计算一下就知道了。如我们要得到 的波特率,晶振为.M 和M,定时器1 为模式2,SMOD 设为1,分别看看那所要求的TH1 为何值。代入公式:

         .M

         =(2÷)×((.M/)/(-TH1))

         TH1=

         M

         =(2÷)×((M/)/(-TH1))

         TH1≈.

         上面的计算可以看出使用M 晶体的时候计算出来的TH1 不为整数,而TH1 的值只能取整数,这样它就会有一定的误差存在不能产生精确的 波特率。当然一定的误差是可以在使用中被接受的,就算使用.M 的晶体振荡器也会因晶体本身所存在的误差使波特率产生误差,但晶体本身的误差对波特率的影响是十分之小的,可以忽略不计。

       ATS是一个低功耗,高性能CMOS 8位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-指令系统及C引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,功能强大的微型计算机的ATS可为许多嵌入式控制应用系统提供高性价比的解决方案。

         ATS具有如下特点:个引脚,4k Bytes Flash片内程序存储器, bytes的随机存取数据存储器(RAM),个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。 

         此外,ATS设计和配置了振荡频率可为0Hz并可通过软件设置省电模式。空闲模式下,CPU暂停工作,而RAM定时计数器,串行口,外中断系统可继续工作,掉电模式冻结振荡器而保存RAM的数据,停止芯片其它功能直至外中断激活或硬件复位。同时该芯片还具有PDIP、TQFP和PLCC等三种封装形式,以适应不同产品的需求。

         1.主要特性:

         •  CPU与MCS- 兼容

         • 4K字节可编程FLASH存储器(寿命:写/擦循环)

         • 全静态工作:0Hz-KHz

         • 三级程序存储器保密锁定

         • *8位内部RAM

         • 条可编程I/O线

         • 两个位定时器/计数器

         • 6个中断源

         • 可编程串行通道

         • 低功耗的闲置和掉电模式

         • 片内振荡器和时钟电路

         2.管脚说明:

         VCC:供电电压。

         GND:接地。

         P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

         P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。

         P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

         P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

         P3.0 RXD(串行输入口)

         P3.1 TXD(串行输出口)

         P3.2 /INT0(外部中断0)

         P3.3 /INT1(外部中断1)

         P3.4 T0(记时器0外部输入)

         P3.5 T1(记时器1外部输入)

         P3.6 /WR(外部数据存储器写选通)

         P3.7 /RD(外部数据存储器读选通)

         P3口同时为闪烁编程和编程校验接收一些控制信号。

         I/O口作为输入口时有两种工作方式即所谓的读端口与读引脚读端口时实际上并不从外部读入数据而是把端口锁存器的内容读入到内部总线经过某种运算或变换后再写回到端口锁存器只有读端口时才真正地把外部的数据读入到内部总线上面图中的两个三角形表示的就是输入缓冲器CPU将根据不同的指令分别发出读端口或读引脚信号以完成不同的操作这是由硬件自动完成的不需要我们操心1然后再实行读引脚操作否则就可能读入出错为什么看上面的图如果不对端口置1端口锁存器原来的状态有可能为0Q端为0Q^为1加到场效应管栅极的信号为1该场效应管就导通对地呈现低阻抗,此时即使引脚上输入的信号为1也会因端口的低阻抗而使信号变低使得外加的1信号读入后不一定是1若先执行置1操作则可以使场效应管截止引脚信号直接加到三态缓冲器中实现正确的读入由于在输入操作时还必须附加一个准备动作所以这类I/O口被称为准双向口C的P0/P1/P2/P3口作为输入时都是准双向口接下来让我们再看另一个问题从图中可以看出这四个端口还有一个差别除了P1口外P0P2P3口都还有其他的功能 

         RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

         ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

         /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

         /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加V编程电源(VPP)。

         XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

         XTAL2:来自反向振荡器的输出。

相关栏目:热点

.重点关注