AVR单片机SREG寄存器详解:中断控制与通用标志位功能

需积分: 50 7 下载量 160 浏览量 更新于2024-08-16 收藏 455KB PPT 举报
SREG寄存器在AVR单片机中扮演着至关重要的角色,它是程序状态寄存器,类似于MCS51中的PSW。这个16位寄存器包含了多个标志位,用于监控和控制单片机的工作状态。以下是SREG寄存器的主要组成部分及其功能: 1. 中断控制:I位是全局中断触发禁止位,当该位清零时,所有中断都会被禁止,除了异步工作模式下TC2的中断唤醒功能。这对于确保程序执行的连续性和处理优先级是关键。 2. 通用标志位(T):T位是一个通用标志,可以用来存储或检测程序执行中的重要标志。通过BLD指令,可以将标志位写入T位,而BST指令则可以读取并用于快速判断。 3. 半进位标志(H):H位用于指示低四位向高四位产生的进位或借位,这在实现十进制加减法的软件调整(DAA)功能以及数字钟的计数调整时非常有用。 4. 符号标志(S):S位是符号标志,它在正常运算条件下等于N而不溢出时,能正确指示运算结果的符号。溢出时,虽然N不能准确反映结果,但S=NV仍能提供部分信息。 5. 溢出标志(V):V位是溢出标志,用于检测加减运算是否产生了溢出,溢出意味着运算结果超出了表示范围。溢出时,运算结果的最高位(N)会反转表示真正的符号。 6. 负数标志(N):N位表示运算结果的正负,但溢出时N不能反映实际结果,因为溢出导致了错误的符号判断。 7. 零标志(Z):Z位用来标记算术或逻辑运算的结果是否为零,对于字节型数据,如果所有位都是0,Z位会被置位。在多字节数据运算中,Z的逻辑表达式基于所有参与运算的数据位。 8. 进/借位标志(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 上传