资讯详情

嵌入式课程作业记录(3)——ARM复习提纲(下)

考试题型:选择题40分(20题),填空题10分(5题),简答题20分(4题),读程序20分(4题),写程序10分(1题)。

留个存档作为记录,因为复习提纲太长,所以分两篇发。

ARM复习大纲(下)

    • 16. 等待寄存器的总线宽度BWSCON、Bank控制寄存器BANKCONn中断向量表和堆栈的初始化程序(注释)?
    • 17. S3C2410电源控制模式有四种模式:正常、慢速、空闲和电源关闭
    • 18. 汇编语言和C混合编程通常有哪些方法?
    • 19. ARM汇编语言与C语言混合编程子程序之间的调用必须遵循一定的调用规则,统称为ATPCS
    • 20. ucos核心调度特点(P98)
    • 21. ucos TCB的内容(P100)
    • 22. ucos就绪表、写表(登记)、删表算法(P100) 查询最高优先级算法(P101)(填空)
      • (1)就绪表
      • (2)写表、删表
      • (3)从就绪表中找到优先级最高的任务
    • 23. Task任务管理类create(P104),Sem同步类create、pend、post(P105),Mbox通信类create、pend、post使用方法(读程序题,写程序题)(P105)
      • (1)任务类
      • (2)消息类
      • (3)同步类
      • (4)时间类(补充)
      • (5)内存操作(补充)
    • 24. ucos移植对处理器的要求,移植的四个步骤(P107)
    • 25. C语言选择题、数组、指针和结构的操作会出现
    • 26. 阅读程序(20分)
    • 27. 写程序:ucos的MBOX和SEM(通信和同步机制)A、B、C,A运行1次后,B运行,最后A、B都运行后,C(10分)

16. 等待寄存器的总线宽度BWSCON、Bank控制寄存器BANKCONn中断向量表和堆栈的初始化程序(注释)?

用于设置总线宽度和等待状态。例如,只要配置相应的寄存器值,就可以使用CPU时钟频率变化。

等待控制寄存器的总线宽度BWSCON和BANKCON控制寄存器的初始化程序:

// config.h /* 总线宽度控制定义(0表示8位,1表示16位,2表示32位) */ #define DW8 (0x0) #define DW16 (0x1) #define DW32 (0x2) #define WAIT (0x1<<2) #define UBLB (0x1<<3)  /* Bank定义时序控制(位域) */ #define MT 15 /* 只有正确的存储类型选择Bank6和Bank7有效 (2bit) */ #define Trcd 2 /* RAS到CAS延迟,仅对SDRAM有效 (2bit) */ #define SCAN 0 /* 列出地址位数,只对SDRAM有效 (2bit) */  #define Tacs 13 /* 在nGCSn有效之前,地址信号的建立时间 (2bit) */
#define Tcos 11 /* 在nOE有效之前,片选的建立时间 (2bit) */
#define Tacc 8 /* 访问周期 (3bit) */
#define Tcoh 6 /* nOE结束之后,片选信号的保持时间 (2bit) */
#define Tcah 4 /* nGCSn结束之后,地址信号的保持时间 (2bit) */
#define Tacp 2 /* Page模式的访问周期 (2bit) */
#define PMC 0 /* Page模式配置 (2bit) */

/**** 外部总线配置,用户可根据实际需要修改 ****/
#define B7_BWCON (DW16|WAIT|UBLB) 
#define B6_BWCON (DW32|UBLB) /* SDRAM所用的Bank,不要修改 */ 
#define B5_BWCON (DW16|WAIT|UBLB) 
#define B4_BWCON (DW16|WAIT|UBLB) 
#define B3_BWCON (DW16|WAIT|UBLB) 
#define B2_BWCON (DW16|WAIT|UBLB) 
#define B1_BWCON (DW16|WAIT|UBLB)

#define B7_BANKCON ((0<<MT)|(1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B6_BANKCON ((3<<MT)|(1<<Trcd)|(1<<SCAN)) /* SDRAM所用的Bank,不要修改 */
#define B5_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B4_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B3_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B2_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B1_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define B0_BANKCON ((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))



// s3c2410.h
// BWSCON寄存器基地址定义
#define BWSCON_ADDR 0x48000000
// Memory control 
#define rBWSCON (*(volatile unsigned *)0x48000000) //Bus width & wait status
#define rBANKCON0 (*(volatile unsigned *)0x48000004) //Boot ROM control
#define rBANKCON1 (*(volatile unsigned *)0x48000008) //BANK1 control
#define rBANKCON2 (*(volatile unsigned *)0x4800000c) //BANK2 cControl
#define rBANKCON3 (*(volatile unsigned *)0x48000010) //BANK3 control
#define rBANKCON4 (*(volatile unsigned *)0x48000014) //BANK4 control
#define rBANKCON5 (*(volatile unsigned *)0x48000018) //BANK5 control
#define rBANKCON6 (*(volatile unsigned *)0x4800001c) //BANK6 control
#define rBANKCON7 (*(volatile unsigned *)0x48000020) //BANK7 control
#define rREFRESH (*(volatile unsigned *)0x48000024) //DRAM/SDRAM refresh
#define rBANKSIZE (*(volatile unsigned *)0x48000028) //Flexible Bank Size
#define rMRSRB6 (*(volatile unsigned *)0x4800002c) //Mode register set for SDRAM
#define rMRSRB7 (*(volatile unsigned *)0x48000030) //Mode register set for SDRAM


// target.c
// 总线配置数据表 (用户可以在config.h文件中配置总线) 
const uint32  __BUS_INIT[] =
{ 
        	
	(B7_BWCON<<28)|(B6_BWCON<<24)|(B5_BWCON<<20)|(B4_BWCON<<16)|(B3_BWCON<<12)|(B2_BWCON<<8)|(B1_BWCON<<4),	// BWSCON寄存器
	B0_BANKCON,			// BANKCON0寄存器
	B1_BANKCON,			// BANKCON1寄存器 
	B2_BANKCON, 		// BANKCON2寄存器
	B3_BANKCON, 		// BANKCON3寄存器
	B4_BANKCON, 		// BANKCON4寄存器
	B5_BANKCON, 		// BANKCON5寄存器
	B6_BANKCON, 		// BANKCON6寄存器 (SDRAM)
	B7_BANKCON, 		// BANKCON7寄存器 (SRAM)
	(1<<23)|(0<<22)|(0<<20)|(3<<18)|(1113),		// REFRESH寄存器(SDRAM) 例如:period=15.6us, HCLK=60Mhz, (2048+1-15.6*60)
	(1<<7)|(1<<5)|(1<<4)|(2<<0),				// BANKSIZE寄存器,128MB
	(3<<4),										// MRSRB6寄存器
	(3<<4)										// MRSRB7寄存器 
};


// target.c
/********************************************************************************************************* ** Function name: TargetBusInit ** Descriptions: 针对目标板的总线系统初始化,包括Bank的宽度、SDRAM控制器等等。 ** 不要在此函数中加入任何用户代码。 ** Input: 无 ** Output: 无 ********************************************************************************************************/
void  TargetBusInit(void)
{ 
           
#ifdef __Release 
    int  i;
    volatile uint32  *cp1;
    							    		
	// 总线设置,初始化SDRAM控制器
	cp1 = (void *)BWSCON_ADDR;
	for(i=0; i<13; i++)
	{ 
        
		*cp1++ = __BUS_INIT[i];		
	}
#endif 
}

中断向量表初始化:

;定义堆栈的大小
USR_STACK_LEGTH     EQU         64
SVC_STACK_LEGTH     EQU         0
FIQ_STACK_LEGTH     EQU         16
IRQ_STACK_LEGTH     EQU         64
ABT_STACK_LEGTH     EQU         0
UND_STACK_LEGTH     EQU         0

			AREA	Example5,CODE,READONLY	; 声明代码段Example5
			ENTRY				; 标识程序入口
			CODE32				; 声明32位ARM指令
START		MOV		R0,#0
			MOV		R1,#1
			MOV		R2,#2
			MOV		R3,#3
			MOV		R4,#4
			MOV		R5,#5
			MOV		R6,#6
			MOV		R7,#7
			MOV		R8,#8
			MOV		R9,#9
			MOV		R10,#10
			MOV		R11,#11
			MOV		R12,#12
			
			BL		InitStack	; 初始化各模式下的堆栈指针
			
			; 打开IRQ中断 (将CPSR寄存器的I位清零)
			MRS		R0,CPSR			; R0 <= CPSR
			BIC		R0,R0,#0x80 
			MSR		CPSR_cxsf,R0	; CPSR <= R0
						
			; 切换到用户模式
        	MSR     CPSR_c, #0xd0
        	MRS		R0,CPSR
        	
        	; 切换到管理模式
        	MSR     CPSR_c, #0xdf
        	MRS		R0,CPSR		

HALT		B		HALT

; 名称:InitStack
; 功能:堆栈初始化,即初始化各模式下的堆栈指针。
; 入口参数:无
; 出口参数:无
; 说明:在特权模式下调用此子程序,比如复位后的管理模式
InitStack    
        	MOV     R0, LR		; R0 <= LR,因为各种模式下R0是相同的

;设置管理模式堆栈
        	MSR     CPSR_c, #0xd3
        	LDR     SP, StackSvc
;设置中断模式堆栈
        	MSR     CPSR_c, #0xd2
        	LDR     SP, StackIrq
;设置快速中断模式堆栈
        	MSR     CPSR_c, #0xd1
        	LDR     SP, StackFiq
;设置中止模式堆栈
        	MSR     CPSR_c, #0xd7
      		LDR     SP, StackAbt
;设置未定义模式堆栈
        	MSR     CPSR_c, #0xdb
        	LDR     SP, StackUnd
;设置系统模式堆栈
        	MSR     CPSR_c, #0xdf
        	LDR     SP, StackUsr

        	MOV     PC, R0

StackUsr   	DCD     UsrStackSpace + (USR_STACK_LEGTH - 1)*4
StackSvc    DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)*4
StackIrq    DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)*4
StackFiq    DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)*4
StackAbt    DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)*4
StackUnd    DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)*4


; 分配堆栈空间 
        	AREA    MyStacks, DATA, NOINIT, ALIGN=2
UsrStackSpace     	SPACE  	USR_STACK_LEGTH * 4 	; 用户(系统)模式堆栈空间
SvcStackSpace      	SPACE  	SVC_STACK_LEGTH * 4  	; 管理模式堆栈空间
IrqStackSpace      	SPACE  	IRQ_STACK_LEGTH * 4  	; 中断模式堆栈空间
FiqStackSpace      	SPACE  	FIQ_STACK_LEGTH * 4  	; 快速中断模式堆栈空间
AbtStackSpace      	SPACE  	ABT_STACK_LEGTH * 4  	; 中止义模式堆栈空间
UndtStackSpace     	SPACE  	UND_STACK_LEGTH * 4  	; 未定义模式堆栈			
			
			
			END	

堆栈初始化:

/********************************************************************************************************* ** 函数名称: OSTaskStkInit ** 功能描述: 任务堆栈初始化代码,本函数调用失败会使系统崩溃 ** 输 入: task : 任务开始执行的地址 ** pdata :传递给任务的参数 ** ptos :任务的堆栈开始位置 ** opt :附加参数,当前版本对于本函数无用,具体意义参见OSTaskCreateExt()的opt参数 ** 输 出: 栈顶指针位置 ** 全局变量: ** 调用模块: ********************************************************************************************************/

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{ 
        
    OS_STK *stk;

    opt    = opt;                           /* 'opt' 没有使用。作用是避免编译器警告 */
    stk    = ptos;                          /* 获取堆栈指针 */

                                            /* 建立任务环境,ADS1.2使用满递减堆栈 */
    *stk = (OS_STK) task;                   /* pc */
    *--stk = (OS_STK) task;                 /* lr */

    *--stk = 0;                             /* r12 */
    *--stk = 0;                             /* r11 */
    *--stk = 0;                             /* r10 */
    *--stk = 0;                             /* r9 */
    *--stk = 0;                             /* r8 */
    *--stk = 0;                             /* r7 */
    *--stk = 0;                             /* r6 */
    *--stk = 0;                             /* r5 */
    *--stk = 0;                             /* r4 */
    *--stk = 0;                             /* r3 */
    *--stk = 0;                             /* r2 */
    *--stk = 0;                             /* r1 */
    *--stk = (unsigned int) pdata;          /* r0,第一个参数使用R0传递 */
    *--stk = (USER_USING_MODE|0x00);	    /* spsr,允许 IRQ, FIQ 中断 */
    *--stk = 0;                             /* 关中断计数器OsEnterSum; */

    return (stk);
}

17. S3C2410电源控制模式有正常、慢速、空闲和电源关断4种模式

18. 汇编语言和C混合编程通常有哪几种方式?

常见的有3种方式:

  • 在C代码中嵌入汇编指令
void string_copy(char *dst,const char *str)
{
  char ch;
  __asm
  {
    loop
      LDRB  ch,[str],#1
      STRB  ch,[dst],#1
      CMP    ch,#0
      BNE loop 
  }
}

int main()
{
  char *a="hello world!"
  char b[64];
  string_copy(a,b);
  return 0;
}
  • C调用汇编:

(1)汇编export

(2)C语言定义 extern function

(3)C语言调用汇编

myArm.s
  AREA  myARM,CODE ,READONLY
  export my_strcopy
my_strcopy
      loop
        LDRB R4,[R0],#1
        CMP  R4,#0
        BEQ OVER
        STRB R4,[R1],#1
        B loop
      OVER
           end

myMain.c

extern void my_strcopy(char *dtr,char*str);
int main()
{
  char *a="hello world!"
  char b[64];
  my_strcopy(a,b);
  return 0;
}
  • 汇编调用C语言:

(1)C语言实现函数

(2)汇编import函数名

(3)BL 函数名

myArm.s
  AREA  myARM,CODE ,READONLY
  IMPORT c_fun
  ENTRY
start
  mov R0,#1
  mov R1,#2
  mov R2,#3
  BL  c_fun
  end

myMain.c
int c_fun(int a,int b,int c)//从汇编中调到这里,此时a=1,b=2,c=3
{
  return a+b+c;//从这里再返回去,此时R0=6;
}

19. ARM汇编语言与C语言混合编程的子程序之间的调用必须遵循一定的调用规则,这些规则统称为ATPCS

ATPCS即ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)的简称。 PCS规定了应用程序的函数可以如何分开地写,分开地编译,最后将它们连接在一起,所以它实际上定义了一套有关过程(函数)调用者与被调用者之间的协议。

PCS强制实现如下约定:调用函数如何传递参数(即压栈方法,以何种方式存放参数),被调用函数如何获取参数,以何种方式传递函数返回值。

部分规则:

20. ucos内核调度特点(P98)

uC/OS内核调度主要有以下特点:

  • 只支持基于优先级的抢占式调度算法,不支持时间片轮训。
  • 64个优先级,只能创建64个任务,用户只能创建56个任务。有一个优先级最低的空闲任务,在没有用户任务时运行。
  • 每个任务优先级都不相同。0优先级最高,63优先级最低。
  • 不支持优先级逆转。
  • READY队列通过内存映射表实现快速查询,效率非常高。
  • 支持时钟节拍。
  • 支持信号量、消息队列、事件控制块、事件标志组、消息邮箱任务通信机制。
  • 支持中断嵌套,嵌套层数可达255层,中断使用当前任务的堆栈保存上下文。
  • 每个任务都有自己的堆栈,堆栈大小有用户自行决定。
  • 支持动态修改任务优先级。
  • 任务TCB为静态数组,建立任务只是从中获得一个TCB,不用动态分配,释放内存。
  • 任务堆栈为用户静态或动态创建,在任务创建外完成,任务创建本身不进行动态内存分配。
  • 任务的总个数(OS_MAX_TASKS)由用户决定。

21. ucos TCB的内容(P100)

(都是些什么乱七八糟的)

主要参数的功能如下:

  • *OSTCBStkPtr是指向当前任务栈顶的指针。
  • *OSTCBExtPtr是任务扩展模块使用。
  • *OSTCBStkBottom是指向任务堆栈栈底的指针。
  • OSTCBStkSize是存有栈中可容纳的指针元数目。
  • OSTCBOpt把“选择项”传给函数OSTashCreateExt()。只有当用户将OS_CFG.H文件中的OS_TASK_CREATE_EXT设为1时,这个变量才有效。
  • OSTCBId用于存储任务的识别码(ID)。
  • OSTCBNextOSTCBPrev用于任务控制OS_TCBs的双向链表的前后连接,该链表在时钟节拍函数OSTimerTick()
  • OSTCBEventPtr是指向事件控制块的指针。
  • OSTCBMsg是指向传给任务消息的指针。
  • OSTCBDly当需要把任务延时若干个时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事件的发生。
  • OSTCBStat是任务的状态字。
  • OSTCBPrio是任务优先级,高优先级任务的OSTCBPrio值最小。
  • OSTCBDelReq是一个布尔量,用于表示该任务是否需要删除。
  • OSTCBX OSTCBY OSTCBBitX OSTCBBitY用于加速任务进入就绪态的过程或进入等待事件发声状态的过程。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。

22. ucos就绪表、写表(登记)、删表算法(P100) 查询最高优先级算法(P101)(填空)

(1)就绪表

任务就绪表记录了系统中所有处于就绪状态的任务,从代码上来看它就是一个类型为INT8U的数组OSRdyTbl[]。。系统中的任务为32个时,OSRdyTbl[]就有4个成员。每个成员占据8位,所以OSRdyTbl[]的每一个数据元素对应8个任务,这8个任务称为一个任务组。在就绪表中,以任务优先二进制位,当该位为1时表示对应的任务处于就绪状态,反之为非就绪状态。

考虑到查找效率,uCOS-II定义了一个INT8U的变量OSRdyGrp,该变量的每一位都对应OSRdyTbl[]的一个任务组(即数据的一个成员)。若某任务任务所对应的位置置为1,否则为0。

举例:OSRdyGrp=00001011,那么就意味着OSRdyTbl[0]、OSRdyTbl[1]、OSRdyTbl[3]中有就绪的任务。由图可知,uCOS-II最多可以管理8 * 8 = 64个任务。

任务就绪表是以任务的优先级从低到高排序的,那么想要根据任务的优先级来找到该任务所处于就绪表中位置就轻而易举了:

由于系统至多支持64个任务,所以优先级至多也就到63,即二进制的00111111,只占据低6位,每一个OSRdyTbl[]元素只是占据8,所以只需要用3个二进制位即可表示这8位中的哪一位为1,同理,高3位用于表示至多8个OSRdyTbl[]元素的哪一个元素。即:

举例:某任务的优先级prio=24,问该任务落在就绪表中的哪一位?

24的二进制位为00011000,D5、D4、D3位011,即OSRdyTbl[]的下标为3,D2、D1、D0为0,即优先级prio=24的任务在OSRdyTbl[3]的第0位。OSRdyGrp的第3位置位。

每个任务的就绪态标志都放入到就绪表中,就绪表中有两个变量OSRdyGrpOSRdyTbl[]

OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组是否有进入就绪态的任务。

任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置为1。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO

为确定下次该哪个优先级的任务运行了,内核调度器总是将最低优先级的任务在就绪表中相应字节的相应位置1,即OS_LOWEST_PRIO = 1

(2)写表、删表

使任务进入就绪表(通过OSMapTbl[]来在就绪表相应的行和列置1):

OSRdyGrp           |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

任务优先级的低三位用于确定任务在总就绪表OSRdyTbl[]中的所在位,接下去的三位用于确定是在OSRdyTbl[]数组的第几个元素。OSMapTbl[]用于限制OSRdyTbl[]数组元素下标为0-7。

从就绪表中删除一个任务(通过OSMapTbl[]来在就绪表相应的行和列置0):

if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
   OSRdyGrp &= ~OSMapTbl[prio >> 3];

将就绪任务表数组OSRdyTbl[]中相应元素的相应位清0。而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时才将相应位清0,即OSRdyTbl[prio >> 3]所有位为0时,OSRdyGrp的相应位才清零。

(3)从就绪表中查找优先级最高的任务

使用的是哈希算法。

所以要找出优先级最高的任务,分两步:

第一步,确定任务组(OSRdyTbl[]的下标)Y:找出OSRedyGrp中为1的最低位Y;

第二步,确定任务组中的位X:找出任务组中OSRdyTbl[x]中为1的最低位X。

综上,找出目标任务的核心算法在于确定某数值为1的最低位,uCOS-II的具体实现是,借助OSUnMapTbl[]数组:

例如0x06(00000110),为1的最低位是Bit[1],那么OSUnMapTbl[0x06]=1;0x20(00100000),为1的最低位是Bit[5],即OSUnMapTbl[0x20]=5。

INT8U   y;
y             = OSUnMapTbl[OSRdyGrp]; //最高优先级所在的任务组     
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); //最高优先级任务所在的任务组的位

INT8U  const  OSUnMapTbl[256] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x00 to 0x0F  */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x10 to 0x1F */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x20 to 0x2F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x30 to 0x3F */
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x40 to 0x4F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x50 to 0x5F */
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x60 to 0x6F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x70 to 0x7F */
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x80 to 0x8F */
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x90 to 0x9F */
    

标签: 传感器tcb

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台