(学习日记)2024.03.07:UCOSIII第九节:时间戳

news2024/11/18 14:56:13

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.03.06

  • 二十一、UCOSIII:时间戳
    • 1、时间戳简介
    • 2、时间戳的实现
    • 3、时间戳代码讲解
      • 1. CPU_Init()函数
      • 2. CPU_TS_Init()函数
      • 3. CPU_TS_TmrInit()函数
      • 4. BSP_CPU_ClkFreq()函数
      • 5. CPU_TS_TmrFreqSet()函数
      • 6. CPU_TS_TmrRd()函数
      • 7. OS_TS_GET()函数
  • 二十二、UCOSIII:修改main()函数
    • 1、修改代码
    • 2、仿真

二十一、UCOSIII:时间戳

1、时间戳简介

本章实现时间戳用的是ARM Cortex-M系列内核中的DWT这个外设的功能, 有关这个外设的功能和寄存器说明具体见手册“STM32F10xxx Cortex-M3 programming manual”

在μC/OS-III中,很多地方的代码都加入了时间测量的功能,比如任务关中断的时间,关调度器的时间等。
知道了某段代码的运行时间,就明显地知道该代码的执行效率,如果时间过长就可以优化或者调整代码策略。

如果要测量一段代码A的时间,那么可以在代码段A运行前记录一个时间点TimeStart, 在代码段A运行完记录一个时间点TimeEnd,那么代码段A的运行时间TimeUse就等于TimeEnd减去TimeStart。
这里面的两个时间点TimeEnd和TimeStart,就叫作时间戳,时间戳实际上就是一个时间点。

2、时间戳的实现

通常执行一条代码是需要多个时钟周期的,即是ns级别。要想准确测量代码的运行时间,时间戳的精度就很重要。 通常单片机中的硬件定时器的精度都是us级别,远达不到测量几条代码运行时间的精度。

在ARM Cortex-M系列内核中,有一个DWT的外设,该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器, 记录的是内核时钟HCLK运行的个数,当CYCCNT溢出之后,会清零重新开始向上计数。该计数器在μC/OS-III中正好被用来实现时间戳的功能。

在STM32F103系列的单片机中,HCLK时钟最高为72M,单个时钟的周期为1/72us = 0.0139us = 14ns, CYCCNT总共能记录的时间为232*14=60S。在μC/OS-III中,要测量的时间都是很短的,都是ms级别, 根本不需要考虑定时器溢出的问题。如果内核代码执行的时间超过s的级别,那就背离了实时操作系统实时的设计初衷了,没有意义。

3、时间戳代码讲解

1. CPU_Init()函数

CPU_Init()函数在cpu_core.c中实现
在这里插入图片描述

/* CPU初始化函数 */
void  CPU_Init (void)
{
/* CPU初始化函数中总共做了三件事
   1、初始化时间戳
   2、初始化中断失能时间测量
   3、初始化CPU名字
   这里只讲时间戳功能,剩下两个的初始化代码则删除不讲 */
	
#if ((CPU_CFG_TS_EN     == DEF_ENABLED) || \
     (CPU_CFG_TS_TMR_EN == DEF_ENABLED))
    CPU_TS_Init();
#endif
	
}

CPU_Init()函数在cpu_core.c中实现, 主要做三件事:

  • 1、初始化时间戳,
  • 2、初始化中断禁用时间测量,
  • 3、初始化CPU名字。

目前第2和3个功能目前还没有使用到, 只实现了第1个初始化时间戳的代码

CPU_CFG_TS_EN和CPU_CFG_TS_TMR_EN这两个宏在cpu_core.h中定义, 用于控制时间戳相关的功能代码
在这里插入图片描述
CPU_CFG_TS_32_EN和CPU_CFG_TS_64_EN这两个宏在cpu_cfg.h文件中定义, 用于控制时间戳是32位还是64位的,默认启用32位
在这里插入图片描述

2. CPU_TS_Init()函数

CPU_TS_Init()是时间戳初始化函数,在cpu_core.c中实现
在这里插入图片描述
CPU_TS_TmrFreq_Hz是一个在cpu_core.h中定义的全局变量,表示CPU的系统时钟, 具体大小跟硬件相关,如果使用STM32F103系列,那就等于72000000HZ。
CPU_TS_TmrFreq_Hz变量的定义和时间戳相关的数据类型的定义具体见

/*
**********************************************************************************************************
*                                                 宏定义
**********************************************************************************************************
*/


#if    ((CPU_CFG_TS_32_EN == DEF_ENABLED) || \
        (CPU_CFG_TS_64_EN == DEF_ENABLED))
#define  CPU_CFG_TS_EN                          DEF_ENABLED
#else
#define  CPU_CFG_TS_EN                          DEF_DISABLED
#endif

#if    ((CPU_CFG_TS_EN == DEF_ENABLED) || \
(defined(CPU_CFG_INT_DIS_MEAS_EN)))
#define  CPU_CFG_TS_TMR_EN                      DEF_ENABLED
#else
#define  CPU_CFG_TS_TMR_EN                      DEF_DISABLED
#endif

/*
*********************************************************************************************************
*                                          时间戳数据类型
*********************************************************************************************************
*/

typedef  CPU_INT32U  CPU_TS32;

typedef  CPU_INT32U  CPU_TS_TMR_FREQ;
typedef  CPU_TS32    CPU_TS;
typedef  CPU_INT32U  CPU_TS_TMR;


/*
*********************************************************************************************************
*                                          全局变量
*********************************************************************************************************
*/

#if  (CPU_CFG_TS_TMR_EN   == DEF_ENABLED)
CPU_CORE_EXT  CPU_TS_TMR_FREQ  CPU_TS_TmrFreq_Hz;              
#endif

3. CPU_TS_TmrInit()函数

时间戳定时器初始化函数CPU_TS_TmrInit()在cpu_core.c实现

/* 时间戳定时器初始化 */
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  fclk_freq;


    fclk_freq = BSP_CPU_ClkFreq();

    /* 使能DWT外设 */
	BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA;
	/* DWT CYCCNT寄存器计数清0 */
    BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;
/* 注意:当使用软件仿真全速运行的时候,会先停在这里,
         就好像在这里设置了一个断点一样,需要手动运行才能跳过, 
         当使用硬件仿真的时候却不会 */
	/* 使能Cortex-M3 DWT CYCCNT寄存器 */
    BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;

    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}
#endif

初始化时间戳计数器CYCCNT,启用CYCCNT计数的操作步骤:

1、先启用DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1启用。

2、启用CYCCNT寄存器之前,先清零。

3、启用CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1启用。 这三个步骤里面涉及的寄存器定义在cpu_core.c文件的开头

/*
*********************************************************************************************************
*                                             寄存器定义
*********************************************************************************************************
*/
/*
 在Cortex-M内核里面有一个外设叫DWT(Data Watchpoint and Trace),该外设有一个32位的寄存器叫CYCCNT,
 它是一个向上的 计数器,记录的是内核时钟运行的个数,当CYCCNT溢出之后,会清0重新开始向上计数。
 使能CYCCNT计数的操作步骤:
 1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能
 2、使能CYCCNT寄存器之前,先清0
 3、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能
 */
#define  BSP_REG_DEM_CR                       (*(CPU_REG32 *)0xE000EDFC)
#define  BSP_REG_DWT_CR                       (*(CPU_REG32 *)0xE0001000)
#define  BSP_REG_DWT_CYCCNT                   (*(CPU_REG32 *)0xE0001004)
#define  BSP_REG_DBGMCU_CR                    (*(CPU_REG32 *)0xE0042004)

/*
*********************************************************************************************************
*                                            寄存器位定义
*********************************************************************************************************
*/

#define  BSP_DBGMCU_CR_TRACE_IOEN_MASK                   0x10
#define  BSP_DBGMCU_CR_TRACE_MODE_ASYNC                  0x00
#define  BSP_DBGMCU_CR_TRACE_MODE_SYNC_01                0x40
#define  BSP_DBGMCU_CR_TRACE_MODE_SYNC_02                0x80
#define  BSP_DBGMCU_CR_TRACE_MODE_SYNC_04                0xC0
#define  BSP_DBGMCU_CR_TRACE_MODE_MASK                   0xC0

#define  BSP_BIT_DEM_CR_TRCENA                          (1<<24)

#define  BSP_BIT_DWT_CR_CYCCNTENA                       (1<<0)

4. BSP_CPU_ClkFreq()函数

BSP_CPU_ClkFreq()是一个用于获取CPU的HCLK时钟的BSP函数,具体跟硬件相关, 目前只是使用软件仿真,则把硬件相关的代码注释掉,直接手动设置CPU的HCLK的时钟等于软件仿真的时钟25000000HZ。

BSP_CPU_ClkFreq()在cpu_core.c实现

/* 获取CPU的HCLK时钟 
这个是跟硬件相关的,目前我们是软件仿真,我们暂时把跟硬件相关的代码屏蔽掉,
直接手动设置CPU的HCLK时钟*/
CPU_INT32U  BSP_CPU_ClkFreq (void)
{
#if 0 
	RCC_ClocksTypeDef  rcc_clocks;


    RCC_GetClocksFreq(&rcc_clocks);
    return ((CPU_INT32U)rcc_clocks.HCLK_Frequency);
#else
	CPU_INT32U    CPU_HCLK;
	
	
	/* 目前软件仿真我们使用25M的系统时钟 */
	CPU_HCLK = 25000000;
	
	return CPU_HCLK;
#endif
}

5. CPU_TS_TmrFreqSet()函数

CPU_TS_TmrFreqSet()函数在cpu_core.c定义, 具体的作用是把函数BSP_CPU_ClkFreq()获取到的CPU的HCLK时钟赋值给全局变量CPU_TS_TmrFreq_Hz


/* 初始化CPU_TS_TmrFreq_Hz,这个就是系统的时钟,单位为HZ */
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ  freq_hz)
{
    CPU_TS_TmrFreq_Hz = freq_hz;
}
#endif

6. CPU_TS_TmrRd()函数

CPU_TS_TmrRd()函数用于获取CYCNNT计数器的值,在cpu_core.c中定义

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    CPU_TS_TMR  ts_tmr_cnts;

                                                                
    ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;

    return (ts_tmr_cnts);
}
#endif

7. OS_TS_GET()函数

OS_TS_GET()函数用于获取CYCNNT计数器的值,实际上是一个宏定义,将CPU底层的函数CPU_TS_TmrRd()重新取个名字封装, 供内核和用户函数使用,在os_cpu.h头文件定义

#include "cpu_core.h"  //CPU_TS在cpu_core.h定义

/*
*********************************************************************************************************
*                                               时间戳配置
*********************************************************************************************************
*/

#if      OS_CFG_TS_EN == 1u
#define  OS_TS_GET()               (CPU_TS)CPU_TS_TmrRd()
#else
#define  OS_TS_GET()               (CPU_TS)0u
#endif

启用时间戳,在os_cfg.h头文件中启用
在这里插入图片描述

二十二、UCOSIII:修改main()函数

1、修改代码

主函数与上一章区别不大,首先在main()函数开头加入CPU_Init()函数,然后在任务1中对延时函数的执行时间进行测量。
在这里插入图片描述

在这里插入图片描述

/*
************************************************************************************************************************
*                                                 包含的头文件
************************************************************************************************************************
*/
#include "os.h"
#include "ARMCM3.h"

/*
************************************************************************************************************************
*                                                   宏定义
************************************************************************************************************************
*/


/*
************************************************************************************************************************
*                                                  全局变量
************************************************************************************************************************
*/
uint32_t TimeStart;/* 定义三个全局变量 */
uint32_t TimeEnd;
uint32_t TimeUse;

uint32_t flag1;
uint32_t flag2;

/*
************************************************************************************************************************
*                                                  TCB & STACK & 任务声明
************************************************************************************************************************
*/
#define  TASK1_STK_SIZE       20
#define  TASK2_STK_SIZE       20

static   CPU_STK   Task1Stk[TASK1_STK_SIZE];
static   CPU_STK   Task2Stk[TASK2_STK_SIZE];

static   OS_TCB    Task1TCB;
static   OS_TCB    Task2TCB;

void     Task1( void *p_arg );
void     Task2( void *p_arg );

/*
************************************************************************************************************************
*                                                  函数声明
************************************************************************************************************************
*/
void delay(uint32_t count);

/*
************************************************************************************************************************
*                                                    main函数
************************************************************************************************************************
*/
/*
* 注意事项:1、该工程使用软件仿真,debug需选择 Ude Simulator
*           2、在Target选项卡里面把晶振Xtal(Mhz)的值改为25,默认是12,
*              改成25是为了跟system_ARMCM3.c中定义的__SYSTEM_CLOCK相同,确保仿真的时候时钟一致
*/
int main(void)
{
    OS_ERR err;
		
		/* CPU初始化:1、初始化时间戳 */
    CPU_Init();

    /* 关闭中断 */
    CPU_IntDis();

    /* 配置SysTick 10ms 中断一次 */
    OS_CPU_SysTickInit (10);

    /* 初始化相关的全局变量 */
    OSInit(&err);

    /* 创建任务 */
    OSTaskCreate ((OS_TCB*)      &Task1TCB,
                (OS_TASK_PTR ) Task1,
                (void *)       0,
                (CPU_STK*)     &Task1Stk[0],
                (CPU_STK_SIZE) TASK1_STK_SIZE,
                (OS_ERR *)     &err);

    OSTaskCreate ((OS_TCB*)      &Task2TCB,
                (OS_TASK_PTR ) Task2,
                (void *)       0,
                (CPU_STK*)     &Task2Stk[0],
                (CPU_STK_SIZE) TASK2_STK_SIZE,
                (OS_ERR *)     &err);

    /* 将任务加入到就绪列表 */
    OSRdyList[0].HeadPtr = &Task1TCB;
    OSRdyList[1].HeadPtr = &Task2TCB;

    /* 启动OS,将不再返回 */
    OSStart(&err);
}



/*
************************************************************************************************************************
*                                                    函数实现
************************************************************************************************************************
*/
/* 软件延时 
void delay (volatile uint32_t count)
{
	for(; count!=0; count--);
}
*/


/* 任务1 */
void Task1( void *p_arg )
{
    for ( ;; ) {
        flag1 = 1;
        //delay( 100 );
        
				TimeStart = OS_TS_GET();
        OSTimeDly(20);
        TimeEnd = OS_TS_GET();
        TimeUse = TimeEnd - TimeStart;
				
        flag1 = 0;
        //delay( 100 );
        OSTimeDly(2);

        /* 任务切换,这里是手动切换 */
        //OSSched();
    }
}

/* 任务2 */
void Task2( void *p_arg )
{
    for ( ;; ) {
        flag2 = 1;
        //delay( 100 );
        OSTimeDly(2);
				//延时函数均替代为阻塞延时,延时时间均为2个SysTick中断周期,即20ms。
				
        flag2 = 0;
        //delay( 100 );
        OSTimeDly(2);

        /* 任务切换,这里是手动切换 */
        //OSSched();
    }
}




2、仿真

时间戳时间测量功能在软件仿真的时候使用不了,只能硬件仿真,这里仅能够讲解代码功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1499018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

排序算法:冒泡排序和简单选择排序

一、冒泡排序 1.冒泡排序的基本原理 对存放原始数组的数据&#xff0c;按照从前往后的方向进行多次扫描&#xff0c;每次扫描都称为一趟。当发现相邻两个数据的大小次序不符合时&#xff0c;即将这两个数据进行互换&#xff0c;如果从小大小排序&#xff0c;这时较小的数据就…

【机器学习300问】28、什么是决策树?

〇、两个预测任务 &#xff08;1&#xff09;任务一&#xff1a;银行预测偿还能力 当前&#xff0c;某银行正致力于发掘潜在的放贷用户。他们掌握了每位用户的三个关键特征&#xff1a;房产状况、婚姻状况以及年收入。此外&#xff0c;银行还拥有过往这些用户的债务偿还能力的…

【办公类-39-03】批量下载微信公众号图片(三)-微信公众号链接的爬虫下载

背景需求&#xff1a; 测试两种公众号图片下载&#xff0c; 1、UIBOT下载速度慢&#xff0c;也需要有UIBOT软件 【办公类-39-01】批量下载微信公众号图片&#xff08;一&#xff09;UIBOT图片下载-CSDN博客文章浏览阅读289次。【办公类-39-01】批量下载微信公众号图片&#…

Paddle上手实战——NLP经典cls任务“推特文本情感13分类”

Paddle上手实战——NLP经典cls任务“推特文本情感13分类” 实战背景介绍 数据地址:https://www.heywhale.com/home/activity/detail/611cbe90ba12a0001753d1e9/content Twitter推文具备多重特性,首要之处在于其与Facebook的显著区别——其完全基于文本形式,通过Twitter接…

使用 Logstash 丰富你的 Elasticsearch 文档

作者&#xff1a;来自 Elastic David Pilato 我们在上一篇文章中看到&#xff0c;我们可以使用摄取管道中的 Elasticsearch Enrich Processor 在 Elasticsearch 中进行数据丰富。 但有时&#xff0c;你需要执行更复杂的任务&#xff0c;或者你的数据源不是 Elasticsearch&#…

Android14音频进阶:AIDL数据转换关键图解(五十九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

光线追踪12 - Defocus Blur(虚焦模糊)

现在我们的最后一个特性是虚化模糊。注意&#xff0c;摄影师通常称之为景深&#xff0c;所以请确保在光线追踪的朋友中只使用虚化模糊这个术语。 真实相机具有虚化模糊是因为它们需要一个大孔&#xff08;而不仅仅是针孔&#xff09;来收集光线。一个大孔会导致所有物体失去焦点…

[HackMyVM]Quick 2

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

MySQl基础入门⑥

上一章知识内容 1.数据类型的属性 2.MySql的约束 mysql的约束时指对数据表中数据的一种约束行为&#xff0c;约束主要完成对数据的检验&#xff0c;如果有互相依赖数据&#xff0c;保证该数据不被删除。它能够帮助数据库管理员更好地管理数据库&#xff0c;并且能够确保数据库…

算法打卡day11|栈与队列篇03|Leetcode 239. 滑动窗口最大值、347.前 K 个高频元素

小顶堆和大顶堆 小顶堆&#xff08;Min Heap&#xff09;和大顶堆&#xff08;Max Heap&#xff09;是两种特殊的完全二叉树&#xff0c;它们遵循特定的堆属性&#xff0c;即父节点的值总是小于或等于&#xff08;小顶堆&#xff09;或者大于或等于&#xff08;大顶堆&#xf…

微信小程序开发系列(二十二)·wxml语法·双向数据绑定model:的用法

目录 1. 单向数据绑定 2. 双向数据绑定 3. 代码 在 WXML 中&#xff0c;普通属性的绑定是单向的&#xff0c;例如&#xff1a;<input value"((value))"/> 如果希望用户输入数据的同时改变 data 中的数据&#xff0c;可以借助简易双向绑定机制。在对应属性…

文心一言 VS 讯飞星火 VS chatgpt (210)-- 算法导论16.1 1题

一、根据递归式(16.2)为活动选择问题设计一个动态规划算法。算法应该按前文定义计算最大兼容活动集的大小 c[i,j]并生成最大集本身。假定输入的活动已按公式(16.1)排好序。比较你的算法和GREEDY-ACTIVITY-SELECTOR的运行时间。如何要写代码&#xff0c;请用go语言。 文心一言&…

阿里云和腾讯云区别价格表,云服务器费用对比2024年最新

2024年阿里云服务器和腾讯云服务器价格战已经打响&#xff0c;阿里云服务器优惠61元一年起&#xff0c;腾讯云服务器61元一年&#xff0c;2核2G3M、2核4G、4核8G、4核16G、8核16G、16核32G、16核64G等配置价格对比&#xff0c;阿腾云atengyun.com整理阿里云和腾讯云服务器详细配…

利用tree命令自动保存文件层级结构

tree命令的使用 为了将上图左侧的文件目录&#xff0c;生成上图右侧中的文件夹结构列表&#xff0c;保存在txt中&#xff0c;使用了如下cmd命令&#xff1a; C:\armadillo-12.8.0>tree .>list.txt以上tree命令分为3部分&#xff1a; tree 命令. 在当前目录>list.tx…

ChatGPT:人工智能的革命与未来

引言 随着人工智能技术的飞速发展&#xff0c;ChatGPT作为OpenAI推出的一款语言模型&#xff0c;已经引起了广泛的关注和讨论。它不仅改变了我们与机器交流的方式&#xff0c;还为众多行业的发展带来了革命性的影响。本文将深入探讨ChatGPT的技术原理、应用场景以及它对未来的…

一些硬件知识(六)

防反接设计&#xff1a; 同步电路和异步电路的区别: 同步电路:存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源&#xff0c;因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。 异步电路:电路没有统一的时钟&#xff0c;有些触发器的时钟输入端与时钟脉冲源相连…

【HarmonyOS】ArkTS-箭头函数

箭头函数 箭头函数是 比普通函数 更简洁 的一种函数写法 () > {}() > {// 函数体 }let 函数名 () > {// 函数体 }let 函数名 () > {// 函数体 } 函数名(实参1, 实参2)let 函数名 (形参1: 类型, 形参2: 类型) > {// 函数体 } 函数名(实参1, 实参2)let 函数名 …

【嵌入式】嵌入式系统稳定性建设:静态代码扫描的稳定性提升术

1. 概述 在嵌入式系统开发过程中&#xff0c;代码的稳定性和可靠性至关重要。静态代码扫描工具作为一种自动化的代码质量检查手段&#xff0c;能够帮助开发者在编译前发现潜在的缺陷和错误&#xff0c;从而增强系统的稳定性。本文将介绍如何在嵌入式C/C开发中使用静态代码扫描…

嵌入式学习第二十五天!(网络的概念、UDP编程)

网络&#xff1a; 可以用来&#xff1a;数据传输、数据共享 1. 网络协议模型&#xff1a; 1. OSI协议模型&#xff1a; 应用层实际收发的数据表示层发送的数据是否加密会话层是否建立会话连接传输层数据传输的方式&#xff08;数据包&#xff0c;流式&#xff09;网络层数据的…

Day22:安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

目录 开发环境 数据导入-mysql架构&库表列 数据库操作-mysqli函数&增删改查 数据接收输出-html混编&超全局变量 第三方插件引用-js传参&函数对象调用 完整源码 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0…