stm32f103c8t6学习笔记(学习B站up江科大自化协)-USART串口-硬件部分

通信协议简介

USART串口

硬件电路

 

通信距离: 

        ·TTL和RS232通信距离只有几十米

        ·RS485电平通信距离可达上千米

应用场景:

        ·TTL用于单片机这种低压小型设备

        ·RS232一般在大型机器上使用,由于环境比较恶劣静电干扰比较大,所以电压电平比较大,允许的波动范围也比较大

        ·RS485是两线压差,也就是差分信号,抗干扰能力较强

串口参数及时序

        串口中,每一个数据都装载在一个数据帧里面,每个数据帧都由 起始位 数据位 和 停止位组成,左边的图数据位有八个,代表一个字节的八位,在右边的图中还可以在最后一位加上一位奇偶校验位,数据位总共就变成了9位。其中有效载荷位是前八位,代表一个字节,校验位跟在有效载荷位后面。

波特率:

        用途:规定串口通信的速率。串口一般是使用异步通信,所以需要双方约定一个通信的速率。比如发送方每隔一秒发送一位,那接收方就得每个一秒接收一位,如果波特率是1000,那么一秒就发送1000位,每一位发送的间隔时间为1ms。如果接收快了就会重复接收某些位,接收慢了就会漏掉某些位。波特率是每秒传输码元的个数,单位是码元/s,或者直接叫波特(Baud),另外还有个速率表示叫比特率,意思是每秒传输的比特数,单位是bit/s,或者叫bps。在二进制调制的情况下,一个码元就是一个bit,此时波特率就等于比特率。单片机串口的通信基本都是比特率调制,高电平表示1,低电平表示0,一位就是1bit。串口的波特率经常会和比特率混用,因为这两个说法的数值相等。注意如果是多进制调制,那么波特率和比特率就不一样。

起始位:

        标志一个数据帧的开始,固定位低电平。串口的空闲状态是高电平,也就是没有数据传输的时候,引脚必须置高电平。要开始传输的时候必须先发送一个起始位,这个起始位必须是低电平来打破空闲时候的高电平,产生一个下降沿。这个下降沿将会告诉接收设备,这一帧数据要开始了。如果没有起始位的话,发送八个1,那么数据线一直是高电平,没有任何数据波动,接收方无法判断是否发送了数据。所以一定要有一个固定为低电平的起始位。

数据位:

        比如发送一个字节是0x0f,先转化为二进制 0000 1111 ,地位先行,所以数据要从地位开始发送,也就是将1111 0000依次放在引脚上。可以按波特率要求,定时翻转电平,产生相应的波形便可以发送该数据。

校验位:

        这里串口使用的是一种叫做奇偶校验的验证方法,用来判断数据传输是否出错。如果数据出错了可以选择丢弃或者要求重传。校验可以选择三种方式,分别是:无校验、奇校验和偶校验。

无校验:

        无校验就是不需要校验位,波形就是左边的图(串口参数及时序下方的图),包含有起始位、数据位和停止位三个部分。

奇偶校验:

        奇校验和偶校验的波形是右边的图(串口参数及时序下方的图),包含起始位、数据位、校验位和停止位四个部分。

奇校验:

        如果使用了奇校验,那么包括校验位在内的9位数据会出现奇数个1,比如传输的是

0000 1111,目前总共是4个1,是偶数个,那么校验位就需要再补一个1,连同校验位一共就是0000 1111 1 一共五个1,保障1为奇数。如果数据是0000 1110一共三个1是奇数个,那么校验位就补一个0,连同校验位一共就是0000 1110 0,总共还是3个1。发送方在发送数据后会补一个校验位,保证1的个数为奇数。接收方在接收数据后会验证数据位和校验位,如果1的个数还是奇数,那就认为数据没有出错。如果在传输过程中,因为干扰有一位由1变为0,或者由0变成1,那么整个数据的奇偶特性就会发生变化,接收方一验证,发现1的个数不是奇数,那就认为传输出错,可以选择丢弃或者重传。

偶校验:

        保证1 的个数是偶数,校验方法同理奇校验。

缺点:

        当两位数据同时出错时,奇偶特性不变时,那就校验不出,奇偶校验只能保证一定程度上的校验。如果要求更高的检出率,可以使用CRC校验,好用但是复杂

停止位:

        同理,在一个字节数据发送完成之后必须要有一个停止位。这个停止位的左右是,用于数据帧的间隔,固定为高电平。同时这个停止位也是为了下一个起始位做准备。如果没有起始位,当数据的最后一位是0的时候,下次再发送一帧的时候就没办法产生下降沿。如果没有数据了,引脚也恰好为高电平。那么代表引脚处于空闲状态。

串口时序:

示波器捕捉波形操作方法:

        将探头的GND接在负极,探头接在发送设备的TX引脚。在发送数据时就可以捕捉到这些波形。 

(1)发送0x55:

        

         这是发送0x55时TX引脚发送数据时输出的波形。波特率是9600,所以每一位的时间就是1/9600,大概就是104us,如上图所示,比100us略多一点。没发送数据的时候是空闲时态,发送数据的时候数据帧先发送起始位,产生下降沿代表数据帧开始,数据0x55转为2进制,低位先行,发送1010 1010,八位数据,一位停止,无校验位,之后便是停止位(图中的P处),把引脚置回高电平,这样一个数据帧就完成了。

        在stm32中,根据字节数据翻转高低电平是由USART外设自动完成。也可以手动完成,定时器定一个104us的时间,时间到之后,按照数据帧的要求调用GPIO_WriteBit置高低电平,产生一模一样的波形,也是可以完成串口通信的。TX引脚发送就是置高低电平,显然RX引脚就是读高低电平,定时调用GPIO_ReadInputDataBit读取每一位去拼接成一个字节。当然,接收的时候还需要一个外部中断,在起始位的下降沿触发,进入接收状态,并且对齐采样时钟,然后依次采样八次,这就是接收的逻辑。

(2)发送0XAA:

        在起始位下降沿之后的一个数据帧的时间内,图中的高电平都是作为数据1来看的。当数据帧结束之后(大概在图中P的位置),虽然还是1没有变化,但是已经处于空闲状态,需要等待下一个下降沿来开启新的一帧数据。

(3)波特率更改为一半:

        将波特率改为4800,与前面9600相比,变成了一半而已,那相应的波形时长就会变回原来的二倍,每一位的间隔也大概为208us,也就是之前的两倍。虽然波形的时间拉宽,但是波形的趋势是不变的

(4)增加奇偶校验位:

        增加了偶校验位,数据还是0x55,1的个数是4个,已经是偶数了,所以如图输出校验位C是低电平0,此时包括数据校验位在内的数据总共是偶数个1

(5)停止位:

        串口的停止位是可以进行配置的,可以选择1位、1.5位、2位等,上面的波形是1为停止位,连续发送两次0x55,两个数据帧会连接在一起,中间没有空闲状态。下面的是2位停止位,连续发送两个0x55,如图可见,停止位就是两位的宽度,中间也没有空闲状态,不过数据的分隔将会更宽。

STM32的USART外设:

        ·USART,Synchronous是同步的意思,另外还有个串口叫UART,少了个S,就是异步发射器。一般串口很少使用这个功能,所以使用起来USART和UART没有什么区别。对于stm32来说USART只是比UART多了个时钟而已,但是只支持时钟输出不支持时钟输入,这个模式更多的是为了兼容别的协议或特殊用途使用的,并不支持两个USART之间进行同步通信,也就是说学习串口仅是使用异步通信,即USART和UART没区别。

        ·这个波特率发生器就是用来配置波特率的,本质上就是一个分频器,比如给APB2总线给个72MHz,然后波特率发生器进行一个分频,得到我们想要的波特率时钟,最后在这个时钟下进行收发,就是我们指定的通信波特率。

        ·可配置数据位长度8或9,这里的参数就是我们前面“串口参数与时序”中的图,是包含奇偶校验位的长度,一般不需要校验位就选8位,需要校验位就选9位。停止位长度支持多种停止位,也就是在”串口时序“这个图中,进行连续发送时,停止位长度决定了帧的间隔。常用1位的停止位,其他的较为少用。

        ·硬件流控制:比如A设备有个TX向B设备的RX发送数据,A设备一直在发,发的太快了,B设备处理不过来,如果没有硬件流控制,那B设备只能抛弃新数据或覆盖原数据。如果有硬件流的话,在硬件电路上就会多出一根线,如果B没准备好接收就置高电平,如果准备好了就置低电平,A接收到了B反馈的信号,就只会在B准备好的时候才会发送数据,如果B没准备好那么数据就不会发送出去。硬件流控制可以较好的防止设备B因处理慢而导致数据丢失的问题。

        ·DMA:如果有大量的数据进行收发,可以使用DMA转运数据,减轻CPU的负担

        ·USART1是APB2总线上的设备,USART2和USART3都是APB1总线上的设备,开启时钟的时候需要注意,使用的时候挂载哪个总线影响并不是很大。

USART框图

 

串口数据寄存器:

        右上角这一块,是串口的数据寄存器,发送或接收的字节数据就寄存在这个地方。这里有两个寄存器,一个数TDR(Transmit DR)发送数据寄存器,另一个是RDR(Receive)接收数据寄存器。这两个寄存器占用同一个地址,在程序上只表现为一个寄存器,就是数据寄存器DR(Data Register),但是在实际硬件中分成了两个寄存器。其中TDR是只写的,RDR是只读的。当进行写操作时,数据就写入了TDR,当进行读操作时,数据就从RDR读出来。

数据移位寄存器:

        数据寄存器下边是两个移位寄存器

发送移位寄存器:

        作用:把一个字节的数据一位一位的移出去,正好对应串口协议波形的数据位。关于移位寄存器的工作状态,举个例子,比如某时刻给TDR写入了0x55,,在寄存器里就是二进制存储0101 0101,此时硬件检测到你写入数据了,他就会检查当前移位寄存器是否有数据在进行移位,如果没有则0101 0101会立刻移动到移位寄存器准备发送。当数据从TDR移动到移位寄存器时,会置一个标志位叫TXE(TX Empty),发送寄存器空。检查标志位如果置1了就可以在TDR写入下一个数据了。但TXE置1时其实数据还没有发送出去,只要数据从TDR移动到发送寄存器了,TXE就会置1,我们就可以写入新数据。下一步发送移位寄存器就会在发送器控制的驱动下向右移位,按箭头方向向右一位一位把数据移动到TX引脚,此处也和串口协议规定的低位先行是一致的。当数据移位完成之后,新的数据将会自动从TDR寄存器转移到发送移位寄存器中,如果当前移位寄存器移位还没有完成,TDR的数据就会进行等待,一旦移位完成,就会立即转移进发送移位寄存器。
    优点:有了TDR和移位寄存器的双重缓存,可以保证发送数据的时候数据帧之间不会有空闲,提高了工作效率。


接收移位寄存器:

        作用:数据从RX引脚通向接收移位寄存器,在接收器控制的驱动下,一位一位的读取RX的高低电平,按箭头先放在最高位,然后向右移,移位8次之后就可以接收一个字节了。因为串口协议定义低位先行,所以接收移位寄存器时从高位往低位这个方向移动的,当一个字节移位完成之后,这一个字节的数据就会整体地一下子移动到数据接收寄存器RDR里边去。在转移的过程中依然会置一个标志位RXNE(RX Not Empty),接收寄存器非空,如果发送设备发送过快,接收设备来不及处理,就会出现丢弃或覆盖数据的现象。有了流控就可以避免这个问题,流控的两个引脚nRTS和nCTS。

硬件数据流控:(了解即可,一般不用)

        nRTS(Request To Send):是请求发送,是输出脚,也就是告诉别人我当前能不能接收
        nCTS(Clear      To Send):是清除发送,是输入脚,也就是用于接收别人nRTS的信号的,前面加个n就是低电平有效。

工作模式:

        首先找一另一个支持流控的串口(B),B的 TX 接到stm32(A)的 RX  ,然后A的RTX要输出一个能不能接收数据的反馈信号,接到B的CTS,当A能接受的时候,RTS就发置低电平请求对方发送,B的CTS接收到之后就可以一直发,当A处理不过来时,比如接收寄存器一直没有读,又有新数据过来了,代表A没有及时处理,那么RTS就会置高电平,B的CTS接收到就会暂停发送,直到A的数据被读走,RTS被置低电平,B才会继续发送。

        反过来,当A用TX给B发送数据时,A的CTS就要接收到B的RTS,用于判断对方能不能接收。TX和CTS是一对的,RX和RTS是一对的。CTS和RTS要交叉连接

时钟功能:(了解即可,一般不用)

        在图的最右边SCLK,用于产生同步的时钟信号,用于配合发送移位寄存器进行输出,发送移位寄存器每移位一次,同步时钟电平就跳变一个周期。也就是说,有了时钟兼容的输出串口就可以兼容SPI,另外这个时钟也可以做自适应波特率,比如接收设备不确定发送设备给的是什么波特率,便可以通过测量这个时钟的周期,计算得到波特率。

唤醒单元:(了解即可,一般不用)

        作用:实现串口挂载多设备

        串口一般是点对点的通信,一般只支持两个设备互相通信,想发数据的话直接发送就行。而多设备可以在一条总线上挂载多个从设备,每个设备分配一个地址,通信时先进行寻址确定通信对象,再进行数据收发。在 唤醒单元 上方有一个 USART地址 ,先给串口分配一个地址,当发送指定地址时,此设备唤醒开始工作。当发送别的设备地址时,别的设备唤醒开始工作。当设备没收到地址时就会保持沉默,以此来实现多设备的串口通信。

中断控制:

        中断申请位就是右边状态寄存器里的各种标志位。TXE(发送寄存器空)和RXNE(接收寄存器非空)这两个是比较重要的标志位,这两个是用于判断发送状态和接收状态的必要标志位。中断控制就是控制中断能不能通向NVIC。

波特率发生器:

        在图的最下面部分。波特率发生器其实就是分频器。APB时钟进行分频,得到发送和接收移位的时钟。时钟输入时F_{PCLK_{x}}  ,x = 1 或 2,USART挂载在APB2,一般是PCLK2的时钟72MHz。其他的USART都挂载在APB1,一般是PCLK1的时钟36MHz。之后时钟进行分频,除以一个USARTDIV的分频系数,这个系数包含了整数部分和小数部分。有些波特率用72M除以一个整数可能除不尽会有小数,带有误差,这里的分频系数支持小数点后4位,分频更加精准。分频完之后要除以16,得到发送器时钟和接收器时钟通向控制部分。

        在这个板块右边的TE为1,就是发送器使能,发送部分的波特率就有效,如果是RE为1,那就是接收器使能,接收部分的波特率有效。

引脚功能复用表:

        使用USART必须严格按照表里面的引脚来,对应哪一个不得修改

        如这张图,有USART1的重映射,所以有机会换引脚,其他的引脚都没有办法作为USART的引脚。

USART基本结构:

数据帧:

        这个图是在程序中配置8位字长和9位字长的波形对比,这里的字长就是我们前面说过的数据位长度,包含校验位。

9位字长:

        第一条时序明显是TX发送或RX接收的数据帧格式,空闲高电平,起始位低电平,然后根据写入的数据置0或1,依次发送位0至位8,共计9位,最后停止位置1,数据帧结束。其中位8是可能的校验位,通过配置寄存器可配置成奇校验、偶校验或无校验位。这里可配置成八位有效载荷+一位校验位或者9位有效载荷位。一般选择9位字长都是加上校验位的,因为8位有效载荷刚好对应一个字节。

        第二条时序就是前面提及的同步时钟输出功能。在每个数据位之间都有一个时钟的上升沿。时钟的频率和数据速率都是一样的,接收端可以在时钟上升沿进行采样,以便于精准定位每一位数据。时钟的最后一位(图中的虚线部分),可以通过LBCL位控制是否要输出,时钟的极性和相位也可以通过配置寄存器进行配置。

空闲帧:从头到尾都是1
断开帧:从头到尾都是0
    这两个数据帧通常用于局域网协议,串口用不着,了解即可


8位字长的:

        从位0一直到位7,共八位,比上边的少位八。同样最后一个位7也可能是校验位,同样如果选择了八位字长最好选择无校验,否则有效载荷位只剩7位。下面的时钟部分同上。

数据帧停止位:

        可配置为0.5、1、1.5、2共四种,这四种参数的区别就是停止位的长度不一样,第一行是一个停止位,停止位的时长和数据位一位的时长一样,第二行是1.5个停止位,此时停止位就是数据位时长的1.5倍,同理两个停止位就是时长的2倍,0.5倍同上。停止位就是用于控制停止时长的。一般使用1位停止位


起始位侦测:(细节)

        TX定时翻转电平即可,输入较为麻烦,不仅需要保证采样频率和波特率一致,还要保证每次输入采样的位置正好处在每一位的正中间。只有在正中间采样读进来的数据才是最可靠的。如果采样点过于靠前或靠后,可能高低电平正在翻转,电平不稳定,稍有误差就采样错误。另外输入最好对噪声有一定的判断能力,如果是噪声最好置一个标志位进行提醒。
    
    当输入电路侦测到一个数据帧的起始位之后,就会以波特率的频率,连续采样一帧数据。从起始位开始,采集位就要对其位的正中间,只要第一位对其后边必定对齐。在输入部分对采样时钟进行了细分,将会以波特率的16倍进行采样,换句话说就是在一位的时间里进行16次采样。最开始空闲状态置高电平,那采样就一直是1,在某个位置突然采样到0,说明在两次采样之间出现了一次下降沿,如果没有任何噪声,那之后就应该是起始位。在起始位会进行连续16次采样,没有噪声的话16次采样必定都是0,但是实际电路必定有噪声,所以即使出现了下降沿仍需多采样几次以防万一。该电路会在下降沿的第3、5、7次进行一批采样,在8、9、10再进行一批采样,这两批采样中都要求每三位里面至少要有2个0,如果没有噪声那么全是0满足情况,如果有轻微噪声,导致里面2位是0一位是1,哪页算是监测到了起始位,但在状态标志位里会置一个标志位NE(noise error)噪声标志位,作用是提醒数据收到了但是有噪声,谨慎使用。如果三位里只检测到1个0那就不算检测到起始位,可能前面的下降沿是噪声导致的,电路就会忽略前面的数据重新开始捕捉下降沿。如果通过了起始位侦测,那么状态就会由空闲变为接收起始位,同时第8、9、10次的采样位置正好是起始位的正中间,之后的数据位接收都将会在第8、9、10位进行采样,用于保证采样都在位的正中间,这就是起始位侦测和采样位置对其的策略。


数据采样的流程:

从1-16是一个数据位的时间长度,在一个数据位有16个采样时钟,由于起始位侦测已经对齐了采样时钟,所以将会直接在第8、9、10位进行采样,为了保证数据的可靠性,将会连续采样3次,没有噪声的情况下全为1或全为0,全为1就认为收到了1,全为0同理。如果有噪声导致三次采样不全为1或0,那就按照2:1的规则进行,两次为1就认为收到1,0同理。在这种情况下NE也会置1

波特率发生器:

        波特率发生器就是分频器,发生器和接收器的波特率由波特率寄存器BRR里面的DIV确定,DIV分为整数部分和小数部分,可以实现更细腻的分频。波特率 = f_pclk1(或2) / (16 * DIV),这里的16是因为内部还有个16倍波特率的采样时钟,所以这里的 输入时钟 除以 DIV 会等于16倍的波特率。举个例子,要配置USART1为9600的波特率,带入公式为: 9600 = 72 000 000  /(16 * DIV),所以DIV = 468.75,转化成2进制就是 11101 0100.11,写到寄存器中前后剩下的部分补0,就是0001 1101 0100.1100。如果用库函数配置的话直接写即可,库函数会自动帮我们计算。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javaEE13(网站第8章两个课后题)

1、对“jspservletjavabean实现分页查询”功能做如下补充: (1)记录批量删除:每个记录前添加复选框,点击批量删除,删除选中记录。 增加跳转到任意页功能。用户可改变每页记录条数。 页面&am…

wait 和 notify方法

目录 1.1 wait()方法 wait 做的事情: wait 结束等待的条件: 1.2 notify()方法 1.3notifyAll方法 1.4wait()和sleep()对比 由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序. 完成这个协调…

Python 的练手项目有哪些值得推荐?

Python 是一种强大的编程语言,有许多值得推荐的练手项目。以下是一些例子: 数据分析:利用 Python 的数据分析库(如 pandas 和 NumPy)处理和分析数据。你可以尝试对数据进行清洗、可视化,或者构建简单的预测…

4-LINUX--文件操作命令

一、文件查看命令 1. cat 1.1 查看文件内容,示例如下: 1.2 合并文件,示例如下: 1.3 往文件中写入数据, Ctrld 是结束输入,示例如下: 2. more 当一个文件的内容超过一个屏幕能显示的行数…

PCL点云处理之最小二乘球面点云拟合(直接拟合法,完整实验)(二百三十一)

PCL点云处理之最小二乘球面点云拟合(直接拟合法,完整实验)(二百三十一) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 现在假设有这样一群点云,它们分布在一个球的表面,可能并不严格,带有些许噪声,此时我们需要计算球心坐标和球的半径。(这里提供完整的实验过…

[leetcode] 43. 字符串相乘

文章目录 题目描述解题方法相乘累加java代码复杂度分析 题目描述 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整…

怎么免费下载无水印视频素材?赶快收藏这六个网站。

今天来教大家怎么下载无水印视频素材,其中一些是免费的,并且可以在商业项目中使用,这些网站都是无水印视频素材,可以放心使用。 蛙学网: 网站的内容非常丰富多彩,包括风景,夜景,食物…

怎么判断你的模型是好是坏?模型性能评估指标大全!

模型性能评估指标,大家一定不陌生!很多小伙伴们都说难,但是它真的很重要很重要很重要!它会对我们的模型有很多的指导,也会给我们真正做模型的时候提供一些指导性的思想,不然我们看到别人的东西只能跟着人家…

阳光保险MySQL数据库平稳迁移OceanBase,稳定运营超700天

作者简介: 车东兴:于阳光保险就职,深耕保险行业的 IT 领域长达12 年,对保险领域的基础架构实践有深刻的理解与掌握。熟悉多款数据库,具有丰富的数据库运维经验。 王华城:于阳光保险就职,10多年一…

Eclipse安装springboot

Eclipse免费,套件丰富,代码开源,功能强大…推荐! 1 下载eclipse: https://www.eclipse.org/downloads/download.php?file/technology/epp/downloads/release/2023-12/R/eclipse-jee-2023-12-R-win32-x86_64.zip 2 安装Spring框…

【Vue3】什么是路由?Vue中的路由基本切换~

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

AI写真变现项目丨超级训练营SOP手册

出品方: 吴东子团队 x AI破局俱乐部 以下只是该SOP手册的部分介绍,AI写真变现项目上手到变现全流程,需要完整手册的可以dd我。 AI写真 首先什么是AI写真,顾名思义的话可以说成是用AI生成写真照,我们先暂且这么理解&am…

学习数据节构和算法的第15天

单链表的实现 链表的基本结构 #pragma once #include<stdio.h> typedf int SLTDataType; typedy struct SListNode {SLTDataType data;struct SListNode*next; }SLTNode;void Slisprint(SLTNode*phead);打印链表 #include<stdio.h> void SListPrint(SLTNode*phe…

springboot+nacos使用

依赖 nacos服务发现和注册的依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency><dependency><groupId>com.alibaba.cloud</g…

【掌握版本控制:Git 入门与实践指南】操作仓库文件|分支管理

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;泥中に咲く—ウォルピスカーター 0:34━━━━━━️&#x1f49f;──────── 4:46 &#x1f504; ◀️ ⏸ ▶…

基于Springboot的高校汉服租赁网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的高校汉服租赁网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

【清晰易懂】@Mapper注解和BaseMapper爱恨情仇

此问题的提出在于自己没有弄明白一个问题&#xff0c;就是Mapper注解有时候可以不加&#xff0c;有时候又需要加。 先说结论&#xff1a;Mapper注解和BaseMapper类在项目中起着相同的作用&#xff0c;都是为了实现数据库基本简单的CRUD&#xff0c;省去在xml文件中再去写&#…

(一)运行起自己的chatGPT

一、运行步骤 前面所有步骤可以参见https://datawhaler.feishu.cn/docx/BwjzdQPJRonFh8xeiSOcRUI3n8b 二、注意 需要注意的是&#xff1a; 部署起来后&#xff0c;必须使用域名访问才能进入。用ip地址端口访问不成功 三、运行效果 gradio需要额外配置一个外部端口&#x…

Redis + Caffeine = 王炸!!

在高性能的服务架构设计中,缓存是一个不可或缺的环节。在实际的项目中,我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中,只有当缓存的访问没有命中时再查询数据库。在提升访问速度的同时,也能降低数据库的压力。 随着不断的发展,这一架构也产生了改进,在…

移动硬盘无法读取怎么修复?分享三个简单方法

移动硬盘作为现代数据存储的重要工具&#xff0c;一旦出现故障&#xff0c;往往会让我们感到焦虑和困惑。当移动硬盘无法读取时&#xff0c;我们需要冷静分析并采取适当的措施来修复它。本文将为您介绍三种有效的修复方法。 一、检查物理连接与驱动程序 当移动硬盘无法读取时&…