第四讲 串口通信_第1页
第四讲 串口通信_第2页
第四讲 串口通信_第3页
第四讲 串口通信_第4页
第四讲 串口通信_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

上一讲我们讲解了串口的发送操作。这一讲我们继续讲解串口的接收。在学习这个串口接收的过程中,我们要巩固这个状态机的写法,也再熟悉熟悉前几讲讲解的内容。首先回顾一下异步串口通信的数据格式:LS日 MSB_ I0/」5I5I"川SIQ/JIw」 p- 4*~~4*~~►岫位 裁据位 检唉位停止位至闲位由于在空闲状态时,传送线为逻辑“1”状态,而数据的传送总是以一个起始位“0”开始,所以当接收器检测到一个从“1”向“0”的跳变时,便视为可能的起始位(要排除干扰引起的跳变);起始位被确认后,就知道发送器已开始发送,接收器就可以按这个数据通信格式接收后续的数据了;当检测到停止位“1”后就表明一帧字符数据已发送完毕。关于接收器的设计最主要的一点是如何提高采样的准确率,最好是保证采样点处于被采样数据的时间中间点。所以,在接收采样时要用比数据波特率高皿倍(nN1)速率的时钟对数据进行采样。在本程序中用16倍波特率时钟进行采样。结合图示,我们讲解一下如何让采样时刻处于被采样数据的时间中间点:TOC\o"1-5"\h\zW中*1早早早早 || |iiiiiiii \ \1J[j1Ij] 十卜 [心JihAkhhhhiuuuuuuuuinmuuuiiuuL】2345£7B9101112B1415LGI2)4G7«»10启动检醐 勃队肩劫俚 采样故擀在t1时刻若检测到低电平,就开始对这个低电平进行连续的检测当检测了8个时钟周期后,到达t2,此刻,若前面的8个周期都是低电平,则认为检测到了起始脉冲。否则就认为是干扰,重新检测。在检测到起始位后,再计数16个采样时钟周期就到达了第一个数据位的时间中间点t3,在此刻采样数据并进行保存。然后再经过16个周期,就是第二个数据位的时间中间点,在此时刻进行采样;然后,再经过16个周期,就是第三个数据位的时间中间点,在此时刻进行采样…..一直这样采样,直到把所有的数据位采样完毕。在理解完上面这个流程后,我们来按这个编制一下程序。串口接收模块1itziraryieee;usei已已已.std_lugic_l164.all;useieee.st.d_1□giit.h.al1;usei已已已・std_1□gic_unsignecl.all;entityuart_risgeneric(fr;5ii[ilen:integer:=8);一一数才居为TramlHn—1purr.(bclkr.resetr.rxdr:instd_logic;--rx赤数据输入脚r_ready:out.st.d_logic;rlziuf:out.st.cl_Ingitori:7duTiTnt.nu)14 一一);encluart.r;17 一archit.ect.urebehaveofuart_rist.ypestatesisi:iz_i匚11已,ir_sample_st.art_bit.rr_samp1e_dat.a_ljit.,r_st.□p:i;signalstate:states:=r_iLlle;signalrxd_syn:st.d_lugic;signa1siin_rxdr:st.cl_logic;242526272829cc・.IWS-rIH•cIVV•I7•384041424344454647cns-rC1«X>52beginprol: process(rxdr)--用DFF把数据输入脚密:形下,防止干扰beginifrxdr='0'thenrxd_syn<='O';elserxd__syn<='1';endif;endprocess;pro2: process(bclkr,resetr,rxd_syn)variablecount:std_logic_vector(3dounto0);variablerent:integerrange0tofrarnlen:=0;variablerbufs:std_logic_vector(7dounto0);beginifresetr='1'thenstate<=r_idle;count:=,r0000,r;rent:=0;r__ready<='O';elsifrising_edge(bclkr)thencasestateis―j检测是否是起始位whenr_idle=>ifrxd__syn='0'thenstate<=r_samplestart^bit;r_ready<='O'税:测到起始位后才复位r_readytents:=0.coun^:=-0000--^这儿起始位为。已经有一个时钟时间了elsestate<=r_idle;endif;5455when「samplestattbit=>--翰测起始位是否够时间56iftxdsyn=1□1then57ifcount<rr0111rrthen一日个时钟后/再采样5Bcount:=count+lj595t:5it.F:-<=usjzUTiplestartbit;60else一起始位正通.寺始采样数据位615tat&-=::=us:5iiTip1&databit;62count:=p,0000F,;63rent:=□;--开始接收数据位64endif;65else665t.:5l1Z.F:-<=Uidle;67count:=p,0000F,;68endif;6970wtienc_samp1e_data_toit=>712口皿匕<:="1口口「,then--玷个时钾后再采样72count:=coLint+l;73state<:=c_samp1e_data_toit;74else75ifrcnt=franilenthen765t.at.e<=r_st.op;77count;=l-,0000l,F;7Brent.:=0;79elseB0st.at.e<=r_samp1e_data_toitjB1count:=l-,0000l,F;B2rtoufs(rent):=rxd_5yn;——移入数据位B3rent:=rcnt+l;B4endif;B5endif;|86whenrstop=> 省略了对停止位的检恻87rready<='1';—接受数据可读了88rbuf<=rbufs; 更新输出数柩89state<=ridle;90when□thers=>91state<=ridle;92endcase;93endif;94endprocess;endbehave;逐行解释:11:bclk为波特率的16倍。这个同uart_t。12:一帧数据接收完毕信号,可以通知顶层模块来提取数据。该信号在复位后为“0”,在接收完一帧数据后变高,然后直到下一次检测到起始位后,即下一帧数据到来时才复位到“0”。顶层模块可通过检测该信号的上升沿来判断一帧数据是否已经接收完毕。19:用type声明一种枚举类型,用来表示接收状态机的状态。共有五状态:r_idle——空闲状态,r_sample_start_bit——采样起始位状态,r_sample_data_bit 采样数据位状态,r_stop----采样停止位状态。24-31:通过一个D触发器,先把串口的输入信号整形一下,这样可减少干扰引起的检测误判。D触发器的原理的工作机制大家应该明白吧,这里就不再赘述了。33-35:定义一些变量。count为时钟bclk的计数器,因为采用了16倍频的时钟,所以一个数据位会维持16个bclk时钟周期,需要用count来计数。rcnt是对接收到的数据位进行计数。这个和串口的发送程序有点类似的。32-95:通过状态机来接收一帧数据。37-41:系统复位。38:复位后状态机设置为空闲状态。39-40:清零计数器。41:置r_ready为0,表示数据还没接收完毕。42-93:系统正常工作,通过状态机的变化实现一帧数据的接收,用case语句实现状态转变。44-53:描述空闲状态时的执行动作。45-49:若传送线上检测到低电平则立即转入r_sample_start_bit状态,并清零计数器。反之,若没有检测到低电平,则还是使系统处于r_idle状态,还需要不断的去检测传送线的状态。55-68:描述采样到起始位后执行的动作。68:假设在44-53句中检测到的低电平是起始位,则这个低电平应该持续16个时钟(因为是16倍频采样的)。在这16个时钟周期内,若是干扰,则可能会在这16个时钟的时间内检测到高电平。若有,那么状态机就回到x_idle状态,否则就认为已经检测到了起始位。64:在检测到起始位后的8个时钟里总线若一直是低电平,则认为是检测到了起始位,状态机切换至r_sample_data_bit,并初始化一些计数器,准备开始采样数据位。70-85:描述采样数据位时执行的动作。71-73:连续计数16个bclk时钟85:当计数到16个阮虫后,就开始采样传送线的电平状态。78:在检测传送线数据前首先判断是否已经接收完数据位,若是就使状态机转Ar_stop状态,并清零计数器。79-83:若数据位还没有接收完毕,贝IJ80句,保持状态机处于r_sample_data_bit状态,并清零count。82句,把当前传送线的电平状态送入到接收缓冲器rbufs,并通过83句将接收到的数据位计数器加1。86-89:描述采样停止位时执行的动作。在本程序中,我们省略了对停止位的采样,这样做对功能本身不会产生影响。87:置r_ready为1,通知外部数据接收完毕88:更新数据输出缓冲器89:使状态机重新会到x_idle状态,开始下一轮的接收检测。90-91:描述状态机处于其它状态时的动作(假如状态机跑飞)。在其它状态时,将状态机置为x_idle,使状态机正常工作。以上只是编写了一个串口接收的元件,现在编写一个顶层调用模块,调用这个接收元件来接收^^机上通过“串口调试助手”发送的数据,并根据接收到的数据点亮不同的LED。代码如下:--顶层文件,倜用uart._r.vhd^gen_div.vhd文件1itoraryiⅇuseieee.std_logic_Ll64.all;■useieee.std_logic_arith.all;useieee.stdlogicunsigned.all;TOC\o"1-5"\h\z6 — —entitytopisport9 (cIkiiL^reset:instd_logic;--clkin=110IIrxd:instd_Log-ic;--串行榆入数据led:out5td_lQgic_vector(2downto0)--ledKSJ13 — —);endtop;16architectu.rebehaveoftoplbcoinponentgen_divis--分频元件调用声明generic(div_parain:integer:=130);--EE□分频的'产生16*9600的时钟port-21telk:instdLog'ic;beIk:outstd_logicjresetlo:inBt-d._logic);一endconiponent;27eoitiponentuart_ris--串口接收元件调用声明port(tocllrrrresetrwdr:instd_logic:r_ready:outstd_logie;rbuf:outstdlogicvector(7downto0)34 ): 一一endeoitiponerLt;36 signalclk_u:std_logic;--1&倍的波特率时■钟signaluevbuf:stdlogicvector(7downto□“——揍收数据缓冲区signaluevueady:stdlogic;——一帧数据揍收完毕标恙40 begii^uautbaud:gen_divpoutmap--分频元件例化t_clk=>clkinruesetb=>uesetrbclk=>clku);—49 uaut_ueceive:--串口接收元件例化uautupoutrnapi:—bclku=>clk_u|I-ue3etu=>ue3etruxdu=>uxdir

56rread7=>trevtreads.57rbuf=>tevbut58):cq60OJL62accept_data:--根据掺收到的数据做动作63process(revready,,reset,,uevbut,,elkuj64begin65ifreset=111then——复位时■全灭661己日亡二社口口口1■七67eIse68ifrevre

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论