AVR单片机SREG状态寄存器详解

需积分: 13 3 下载量 194 浏览量 更新于2024-07-12 收藏 440KB PPT 举报
"状态寄存器SREG在AVR单片机中的作用和各个标志位的含义,包括I、T、H、S、V、N、Z、C位的功能及其在程序设计中的应用" 状态寄存器SREG是AVR单片机中一个重要的寄存器,类似于MCS51系列单片机的程序状态字PSW,它包含了多个标志位,这些标志位反映了CPU执行算术和逻辑运算的结果,同时也用于控制中断和实现特定的程序逻辑。 1. **全局中断触发禁止位(I)**:I位是中断总控制开关,设置为0会禁止所有中断(除了在异步工作模式下T/C2的中断唤醒功能)。这使得程序员能够临时关闭中断,以避免在关键操作期间被打断。 2. **通用标志位(T)**:T位是一个可以被程序员自由使用的标志位,通过测试T位,可以实现根据不同的条件执行不同的程序功能。例如,可以使用BLD和BST指令来转移其他寄存器的位到T标志位,进行快速的检测和判断。 3. **半进位标志位(H)**:H位用于指示加减运算时低四位到高四位的进位或借位。配合进位标志C,可以实现十进制加减法的软件调整,或者在处理如数字钟这类需要十进制递增的场合。 4. **符号标志位(S)**:S位由N和V标志位的异或运算得到。在无溢出的情况下(V=0),S位正确地反映出运算结果的符号。在溢出时,虽然N标志可能无法正确指示结果的正负,但S标志依然能提供正确的信息。 5. **溢出标志位(V)**:V位标记模2补码运算是否发生溢出,溢出意味着运算结果超出了可表示的范围。在加法中,溢出可能导致正加正等于负或负加负等于正;在减法中,溢出则可能导致正减负等于负或负减正等于正。V标志可以帮助检测并处理这些情况。 6. **负数标志位(N)**:N位直接反映了运算结果的最高位,当N位为1时,表示结果为负数,否则为正数。然而,在溢出情况下,N位并不能准确反映真实结果,此时需参考V标志。 7. **零标志位(Z)**:Z位在运算或比较结果为零时被置位。对于字节数据,如果所有位都为0,Z标志就会被设置,这在判断是否等于零的条件语句中非常有用。 8. **进位/借位标志(C)**:C位记录了在运算过程中最高位的进位或借位。在加法中,C位表示是否有进位;在减法中,C位表示是否有借位。 了解和熟练使用SREG寄存器中的这些标志位,对于编写高效、可靠的AVR单片机程序至关重要,它们可以用于条件分支、错误检测、中断处理等各种程序逻辑控制。

//将16位2进制数data转为5*4位BCD码 reg[3:0] dec_out0=4'h0; reg[3:0] dec_out1=4'h0; reg[3:0] dec_out2=4'h0; reg[3:0] dec_out3=4'h0; reg[3:0] dec_out4=4'h0; wire [15:0] product; assign product=data; wire [15:0] bin_in=product; wire[4:0] c_in; wire[4:0] c_out; reg [3:0] dec_sreg0=4'h0; reg [3:0] dec_sreg1=4'h0; reg [3:0] dec_sreg2=4'h0; reg [3:0] dec_sreg3=4'h0; reg [3:0] dec_sreg4=4'h0; wire[3:0] next_sreg0,next_sreg1,next_sreg2,next_sreg3,next_sreg4; reg [7:0] bit_cnt=8'h0; reg [15:0] bin_sreg; wire load=~|bit_cnt;//读入二进制数据,准备转换 wire convert_ready= (bit_cnt==8'h11);//转换成功 wire convert_end= (bit_cnt==8'h12);//完毕,重新开始 always @ (posedge clk) begin if(convert_end) bit_cnt<=4'h0; else bit_cnt<=bit_cnt+4'h1; end always @ (posedge clk) begin if(load) bin_sreg<=bin_in; else bin_sreg <={bin_sreg[14:0],1'b0}; end assign c_in[0] =bin_sreg[15]; assign c_in[1] =(dec_sreg0>=5); assign c_in[2] =(dec_sreg1>=5); assign c_in[3] =(dec_sreg2>=5); assign c_in[4] =(dec_sreg3>=5); assign c_out[0]=c_in[1]; assign c_out[1]=c_in[2]; assign c_out[2]=c_in[3]; assign c_out[3]=c_in[4]; assign c_out[4]=(dec_sreg4>=5); //确定移位输出 assign next_sreg0=c_out[0]? ({dec_sreg0[2:0],c_in[0]}+4'h6):({dec_sreg0[2:0],c_in[0]}); assign next_sreg1=c_out[1]? ({dec_sreg1[2:0],c_in[1]}+4'h6):({dec_sreg1[2:0],c_in[1]}); assign next_sreg2=c_out[2]? ({dec_sreg2[2:0],c_in[2]}+4'h6):({dec_sreg2[2:0],c_in[2]}); assign next_sreg3=c_out[3]? ({dec_sreg3[2:0],c_in[3]}+4'h6):({dec_sreg3[2:0],c_in[3]}); assign next_sreg4=c_out[4]? ({dec_sreg4[2:0],c_in[4]}+4'h6):({dec_sreg4[2:0],c_in[4]}); //装入数据 always @ (posedge clk) begin if(load) begin dec_sreg0<=4'h0; dec_sreg1<=4'h0; dec_sreg2<=4'h0; dec_sreg3<=4'h0; dec_sreg4<=4'h0; end else begin dec_sreg0<=next_sreg0; dec_sreg1<=next_sreg1; dec_sreg2<=next_sreg2; dec_sreg3<=next_sreg3; dec_sreg4<=next_sreg4; end end //输出 always @ (posedge clk) begin if(convert_ready) begin dec_out0<=dec_sreg0; dec_out1<=dec_sreg1; dec_out2<=dec_sreg2; dec_out3<=dec_sreg3; dec_out4<=dec_sreg4; end end

2023-06-09 上传