当前位置:科普知识站>综合知识>

单片机临界段代码怎么写|嵌入式思考题:什么是临界代码段,进出临界代码段的必须进行是哪行

综合知识 阅读(3W)
1.嵌入式思考题:什么是临界代码段,进出临界代码段的必须进行是哪行

嵌入式还有临界代码这么高端?

单片机临界段代码怎么写 嵌入式思考题:什么是临界代码段,进出临界代码段的必须进行是哪行

计算机世界里面的临界代码段一般是指多线程下多个线程想要执行同一段代码的情况,这一个同一段代码就叫做临界代码段。

具体看你写什么程序,不同程序有不同的要求。

进出临界代码段的话,如果进入的线程数量等于程序要求的最大并发执行数量的话就应该对临界代码段进行锁定,让其他想进入临界代码段的线程进入阻塞状态,等待执行状态的线程执行完以后再申请进入临界代码段。出来也是差不多,线程出临界代码段应该释放有关的代码段资源(一般是弄成信号量、有的书会写叫做同步锁,反正都是一个意思),反正就是解锁,然后进入阻塞状态。

简单来说,线程去申请执行临界代码段,如果发现满足条件将可以执行就执行,如果发现临界代码段被锁定了就挂起进入阻塞,等待能有信号量的时候再去申请。

那一本日本人写的很有名的多线程书的比喻来说,临界代码段其实可以看成是一个房子或者是看成是电梯,人就相当于线程,当电梯到达最大载重的时候,这时候人就不能进入电梯,就好比当前临界代码段同时并发执行的线程到达程序设定的最大数量的时候,就不能再给新的线程进入了,就如电梯那样,再进人就超载了,这个时候想进电梯的人就必须在外面重新等待,等待电梯上的人到达所要到的楼层以后,再腾出空位接新的乘客一样。。。有位置就可以进,没有位置就得等(也就数进入阻塞状态),等到有位置电梯自然会通知你,然后你跟其他人一起重新排队等待进入电梯。。。大概也就是这个过程。

如果觉得说的好,请采纳。

2.单片机代码编写

假设:

P0和P1接数码管显示,

熄灭P1.0用低电平,

按键盘P3.2按下是低电平,

程序如下:

1 ORG 0000H

0000 020030 2 LJMP 0030H

3 ORG 0030H

0030 75803F 4 MOV P0,#3FH

0033 7590FF 5 MOV P1,#0FFH

0036 75A000 6 MOV P2,#00H

0039 C290 7 CLR P1.0

003B D2B2 8 L01: SETB P3.2

003D 20B209 9 JB P3.2,L02

0040 75805B 10 MOV P0,#5BH

0043 75905B 11 MOV P1,#5BH

0046 02003B 12 LJMP L01

0049 75803F 13 L02: MOV P0,#3FH

004C 7590FF 14 MOV P1,#0FFH

004F 02003B 15 LJMP L01

16 END

3.单片机一段代码,求解释

前面改一下 ORG 0000H

LJMP START

ORG 000BH

LJMP TIME0T

ORG 0030H意思是程序从0地址开始跳转主程序,定时器0中断入口地址000BH,主程序地址从0030H开始。

主程序中MOV SP,#70H是指堆栈从70H开始(默认为07H,由于0BH要放定时器0中断的入口地址,07H到0AH明显不够,所以将堆栈开辟到70H后)

MOV TMOD,#01H

MOV TH0,#00H

MOV TL0,#01H

SETB EA

SETB ET0

SETB TR0为定时器0的初始化和开中断

LOOP: INC R1

LJMP LOOP用来无限循环(即等待中断)

当定时器0从0001H开始加直到溢出后从主程序跳到定时器0的中断子程序。

TIME0T: MOV TH0,#00H

MOV TL0,#01H 中断子程序中这两句用来设定初值

MOV A,P1 主程序中给P1赋值为08H,这句将寄存器A赋值08H

JB ACC.0, TT1 这句用来判断寄存器A的最低位是否为1,不是的话A循环右移然后跳转到子程序TT2(TT2的作用是将循环右移后的值重新赋给P1),是的话跳转TT1(TT1的作用是重新赋值A为08H)然后执行TT2即将A的值给P1。

总得来看是原先P1=00001000b,主程序等待,当定时中断触发,在中断子程序中将P1值给A即A=00001000b,显然ACC.0=0,那么执行RR A,这是A=00000100b,TT2中将A的值给P1即P1=00000100b,等待下一次定时器0溢出执行中断子程序,跟上面一样A=00000100b,显然ACC.0任为0,A继续循环右移,A=00000010b,继续以上,下一次循环右移后A=00000001b,再下一次执行JB ACC.0, TT1时,显然ACC.0=1,就跳转TT1即P1重新赋值为08H,就这样不断循环。

可以用来当流水灯。

4.这个单片机代码怎么写 求大神解答最好有注释阿

#include#define uchar unsigned char#define uint unsigned intsbit RED_A=P1^0; //东西向灯sbit YELLOW_A=P1^1;sbit GREEN_A=P1^2;sbit RED_B=P1^5; //南北向灯sbit YELLOW_B=P1^6;sbit GREEN_B=P1^7;uchar Flash_Count=0,Operation_Type=1; //闪烁次数,操作类型变量//延时void DelayMS(uint x){ uchari; while(x--)for(i=0;i<120;i++);}//交通灯切换void Traffic_Light(){ switch(Operation_Type) { case1: //东西向绿灯与南北向红灯亮 RED_A=1;YELLOW_A=1;GREEN_A=0; RED_B=0;YELLOW_B=1;GREEN_B=1; DelayMS(2000); Operation_Type=2; break; case2: //东西向黄灯闪烁,绿灯关闭 DelayMS(300); YELLOW_A=~YELLOW_A;GREEN_A=1; if(++Flash_Count!=10)return; //闪烁5次 Flash_Count=0; Operation_Type=3; break; case3: //东西向红灯,南北向绿灯亮 RED_A=0;YELLOW_A=1;GREEN_A=1; RED_B=1;YELLOW_B=1;GREEN_B=0; DelayMS(2000); Operation_Type=4; break; case4: //南北向黄灯闪烁5次 DelayMS(300); YELLOW_B=~YELLOW_B;GREEN_B=1; if(++Flash_Count!=10)return; Flash_Count=0; Operation_Type=1; }}//主程序void main(){ while(1)Traffic_Light();}。

5.51单片机的一个短代码,帮看看

这是三个问题。

;------------------------------------------

将片内20H~2FH及片外0010H~001FH单元清0;

代码是:

ORG 0000H

CLR A

MOV R0, #20H

IN0:

MOV @R0, A

INC R0

CJNE R0, #30H, IN0

;------------------------------------------

然后将片内30H~3FH的数据移到片外0000H~000FH中;

代码是:

;这里,应该先写一段,对30H~3FH送入数据的程序

MOV R0, #30H

MOV DPTR, #0000H

INN:

MOV A, @R0

MOVX @DPTR, A

INC R0

INC DPTR

CJNE R0, #40H, INN

;------------------------------------------

判断:

若(30H)≤10,则求其平方存到31H中,并将位00H置1(其它位清0)

若(30H)=10, 则将AA存到31H中,并位01H置1(其它位清0)

若(30H)≥10,则减10存到31H中,并位02H置1(其它位清0)

;这里,应该先写一段:对30H送入数据的程序,如:

MOV 30, #10

判断代码是:

CLR 20H.0

CLR 20H.1

CLR 20H.2

MOV A, 30H

CLR C

SUBB A, #10

JZ DENG

JC SMA

BIG:

MOV 31H, A

SETB 20H.2

JMP OUT

SMA:

MOV A, 30H

MOV B, A

MUL AB

MOV 31H, A

SETB 20H.0

JMP OUT

DENG:

MOV 31H, #0AAH

SETB 20H.1

OUT:

SJMP $

END

6.单片机课设代码 要详细讲解

这是我以前自己写的一个实例,你看一下,课程设计还有一些必须东西你自己加,你用这个参考下 实验的目的就是写一个可以调时间的电子时钟。

它使用七段数码管显示。我买的单片机开发板上自带有两个四位的数码管。

一般数码管的显示驱动可以有几种方法,直接驱动显示和循环扫描显示这是两种最常用的方法。用于单片机的IO口只有区区的32个,用直接驱动显示就是很浪费IO口的资源 ,但是它的电路很容易理解。

我用的板子上的数码管是使用循环扫描法显示的。每一个四位数码管都有12根引脚。

其中的8根用于输入信号,4根用来做选通 用。循环扫描是利用人眼的视觉误差来达到显示目的的。

它是一位接一位的选通(直接驱动显示就是同时都选通),它的选通频率非常的高,这样人看起来就好像数码管的每一位都同时在亮。如果一个数码管一秒中亮10次,我们眼睛就可以看到他在闪,如果它一秒亮几万次的话,我们人眼看到的效果就是它一直都在亮而并没有闪。

我第一次写的那个程序就是能够看到数码管在闪,因为我写显示子程序的时候用的延时时间太长了,这样单位时间内选通次数也就减少了,人眼就能看到它在闪了。通过修改延时,将延时时间缩短,改过之后就看不到他在闪了。

下面是我使用的数码管的逻辑电路图,实际电路图也很简单。 它使用P0口用作输入信号,P2口用于输入选通信号。

数码管是使用共阳接法。那么低电平就是有效电平。

选通信号可以看出也是低电平有效。数码管的连接原理也很简单:每一位数码管的每一段和每一位数码管的小数点按序连接到P0端口,8位数码管都这样连接到P0端口,即每一位数码管的第一段并联在一起后然后再与P0.0相串联。

每一位数码管都有一个选通引脚。8位数码管就需要8个选通引脚。

上图中的P2.0--P2.7就是都起选通作用。在写程序的时候就是一位接一位分别选通并且都是通过P0口传送数据。

当有很多位时,可以用一个译码器进行选通这样也能节约IO口资源。如下所示: MOV P0, #DATA CLR P2.0 LCALL DELAY ;延时一段时间 循环赋值并依次选通各位数码管 使用共阳接法的数码管在写程序的时候如果使用查表法的时候那个表格数据可以这样定义: TABLE:DB 0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H, 80H, 90H 在单片机汇编中,8位的立即数如果高四位的值大于等于A,前面一定要加零,否则在编译的时候就会有错误,提示是你的程序中有一个未定义的符号。

不加零时编译器KEIL uvision2将立即数视为符号。我想这是初学者很容易忽略的一个问题。

在用C编写时十六进制立即数只要在其前面加0X就可以了。 下面将这次实例中我做的源程序列出来,然后一点点分析其中要注意的知识点: 源程序;************************************************************************; 这是一个单片机时钟程序,RESET后显示12-00-00; 调时方法:按下S6键后,进入调时设置; 按S3键,可以调整小时; 按S1键,可以调整十分钟位; 按S4键,可以调整分钟位; 按S2键,可以调整十秒位; 按S5键,可以调整秒位; 再次按S6键,退出调时设置;************************************************************************SECOND EQU 30H ;定义显示缓冲区TSECOND EQU 31HMINUTE EQU 32HTMINUTE EQU 33HHOUR EQU 34HTCOUNT EQU 35H ORG 0000H ;中断向量表AJMP MAINORG 0003HLJMP INT_X0ORG 000BHLJMP INT_T0 MAIN:MOV DPTR, #TABLE ;初始化赋值 MOV TCOUNT, #00 MOV SECOND, #00 ;赋显示初值,显示初始化 MOV TSECOND, #00 MOV MINUTE, #00 MOV TMINUTE, #00 MOV HOUR, #12 MOV TMOD, #01H ;定时计数器采用工作方式1 MOV TH0, #0D8H ;赋定时初值为10ms MOV TL0, #0F0H SETB IT0 ;使定时计数器0中断和外部中断0使能 SETB TR0 SETB ET0 SETB EX0 SETB EALOOP:LCALL DISPLAY AJMP LOOP INT_X0:LCALL DELAY ;外部中断0中断服务子程序 JB P3.2, EXIT JNB P3.2, $ LOOP1:LCALL DISPLAY JB P3.2, N1 LCALL DELAY JNB P3.2, EXIT N1:JB P3.3, N2 LCALL DELAY JB P3.3, N2 INC HOUR MOV A, HOUR CJNE A, #24, G1 MOV HOUR, #00 G1:JNB P3.3, $ N2:JB P3.4, N3 LCALL DELAY JB P3.4, N3 INC TMINUTE MOV A, TMINUTE CJNE A, #6, G2 MOV TMINUTE, #00 G2:JNB P3.4, $ N3:JB P3.5, N4 LCALL DELAY JB P3.5, N4 INC MINUTE MOV A, MINUTE CJNE A, #10, G3 MOV MINUTE, #00 G3:JNB P3.5, $ N4:JB P3.6, N5 LCALL DELAY JB P3.6, N5 INC TSECOND MOV A, TSECOND CJNE A, #6, G4 MOV TSECOND, #00 G4:JNB P3.6, $ N5:JB P3.7, NEXT LCALL DELAY JB P3.7, NEXT INC SECOND MOV A, SECOND CJNE A, #10, G5 MOV SECOND, #00 G5:JNB P3.7, $ NEXT:AJMP LOOP1 EXIT: JNB P3.2, $ RETI INT_T0:MOV TH0, #0D8H ;定时器T0中断服务程序入口 MOV TL0, #0F0H INC TCOUNT MOV A, TCOUNT CJNE A, #100, EXIT_T0 INC SECOND MOV TCOUNT, #00 MOV A, SECOND CJNE A, #10, EXIT_T0 INC 。

7.单片机定时器实验的代码怎么写

如果是100ms中断一次,那么晶振需要用6MHz

#include

#define uchar unsigned char

uchar t1,sec1,dscan=0,dis[3]={0,0,0};

uchar table={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

void t0isr() interrupt 1

{

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

t1++;

if(t1>=20)

{

t1=0;

sec1++;

dis[0]=sec1%10;

dis[1]=sec1%100/10;

dis[2]=sec1/100;

}

}

void t1isr() interrupt 3

{

TH1=(65536-5000)/256;

TL1=(65536-5000)%256;

P2=1P0=table[dis[dscan]];

}

main()

{

TMOD=0x11;

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

TH1=(65536-5000)/256;

TL1=(65536-5000)%256;

TR0=1;

ET0=1;

TR1=1;

ET1=1;

EA=1;

t1=0;

sec1=0;

while(1);

}