在校园中,学生、教职工和其他人员通常需要持有一张校园一卡通,用于实现身份识别和各种应用,如进出校门、图书借阅、用餐结算等。传统的校园一卡通系统使用磁条或条形码等技术,但这些技术存在读取速度慢、易受损等问题。为了提升校园一卡通的性能和安全性,某公司考虑采用RFID技术。 使用STC89C52RC微控制器和MF RC500读写器芯片实现校园一卡通的RFID应用。STC89C52RC作为主控芯片,负责控制和处理RFID读写器的功能;MF RC500芯片作为RFID读写器的核心部件,负责与RFID标签进行通信。如下图所示:
添加图片注释,不超过 140 字(可选)
【问题1】(11分) STC89C52RC单片机的主要特性中,正确的选项有: (1) ,错误的选项有: (2) 。 (a)增强型8051单片机,6时钟/机器周期和12时钟/机器周期可以任意选择,指令代码完全兼容传统8051. (b)工作电压:5.5V~3.3V(5V单片机)/3.8V~2.0V(3V单片机) (c)工作频率范围:0~40MHz,相当于普通8051的0~80MHz,实际工作频率可达48MHz (d)用户应用程序空间为8K字节 (e)片上集成512字节RAM (f)通用I/O口(32个)。 (g)不可通过串口直接下载用户程序 (h)不具有EEPROM功能 (i)不具有看门狗功能 (j)共4个16位定时器/计数器。即定时器T0、T1、T2、T3 (k)外部中断4路,下降沿中断或低电平触发电路,Power Down模式可由外部中断低电平触发中断方式唤醒 【问题2】(2分) 在嵌入式系统中,晶体振荡器的主要作用是提供精确的 (3) 给单片机芯片或其他芯片,以确保系统的正常运行和稳定性。 【问题3】(2分) 通过连接MAX232与STC89C52RC单片机,可以实现串口通信的连接,并提供 (4) 的功能,从而实现与其他设备的数据交换和通信操作。
答案:
【问题1】 (1)a、b、c、d、e、f、j、k (2)g、h、i 【问题2】 时钟信号 【问题3】 “电平转换”或者“电平适配”都可得分。
解析:【问题1】 1. 增强型8051单片机,6时钟/机器周期和12时钟/机器周期可以任意选择,指令代码完全兼容传统8051. 2. 工作电压:5.5V~3.3V(5V单片机)/3.8V~2.0V(3V单片机) 3. 工作频率范围:0~40MHz,相当于普通8051的0~80MHz,实际工作频率可达48MHz 4. 用户应用程序空间为8K字节 5. 片上集成512字节RAM 6. 通用I/O口(32个)。 7. 可通过串口直接下载用户程序 8. 具有EEPROM功能 9. 具有看门狗功能 10. 共3个16位定时器/计数器。即定时器T0、T1、T2 11. 外部中断4路,下降沿中断或低电平触发电路,Power Down模式可由外部中断低电平触发中断方式唤醒 12. 通用异步串行口(UART),还可用定时器软件实现多个UART 13. 工作温度范围:-40~+85℃(工业级)/0~75℃(商业级) 【问题2】 在嵌入式系统中,晶体振荡器的作用是提供精确的时钟信号给单片机芯片或其他芯片,以确保系统的正常运行和稳定性。晶体振荡器通过振荡晶体中的谐振频率来产生稳定的振荡信号,用于同步各个模块的操作。 【问题3】 MAX232是一种常见的串口转换芯片,它可以将单片机(如STC89C52RC)的逻辑电平(TTL电平)转换为RS232相关的电平。
2.【说明1】在一个嵌入式车辆追踪器系统中,我们有多种数据类型用于存储和处理数据。这种嵌入式系统用于监控和追踪车辆的位置,它通过GPS模块接收和处理GPS信号,获取车辆的经度、纬度和时间等信息。设备还通过GSM模块,将位置信息发送到服务器。 在这个系统里,我们可能会有一个字符型数据,如车辆标识符,此数据为1个字节。另一种可能的数据类型是整型,用于表示车辆的速度或方向,为每个整型(int)数据分配4个字节。另外,系统可能会使用指针来引用数据,例如用于引用存储车辆实时位置信息的复杂数据结构,每个指针占用4个字节。 因此,根据系统的需求和编程语言的规定,对于每个数据类型,需要分配适当的内存空间。在C语言中,sizeof关键字可以被用于任何数据类型、对象或表达式,返回其所占内存空间的大小,单位是字节。所以sizeof(x)用于计算为x分配的字节数。 【C代码】 #include <stdio.h> #include <string.h> int main() { int arr[5]={10, 20, 30}; char mystr[]="JustAtest\n"; char *ptr=mystr; printf("%d %d %d\n", sizeof(int), sizeof(unsigned int), sizeof(arr)); printf("%d %d\n", sizeof(char), sizeof(mystr); printf("%d %d %d\n", sizeof(ptr), sizeof(*ptr), strlen(ptr)); return 0; } 【说明2】 const是C语言的一个关键字,可以用来定义“只读”型变量。
【问题1】(8分) 请写出以上C代码的运行结果。 【问题2】(4分) (1)请定义一个“只读”型的整型常量size,并将其值初始化为10; (2)请定义一个指向整型变量a的指针ptr,使得ptr的值不能修改,而ptr所指向的目标变量的值可以修改(即可以通过ptr间接修改整型变量a的值)。 注:无需给出整型变量a的定义。 【问题3】(3分) 某C程序文件中定义的函数f如下所示,请简要说明其中static的作用,以及形参表“const int arr[]”中const的作用。 static int f(const int arr[]) { /* 函数体内的语句省略 */ }
答案:
【问题1】 4 4 20 1 11 4 1 10 【问题2】 (1)const int size=10; 或 int const size=10; (2)int* const ptr=&a; 【问题3】 static的作用:说明是f内部函数,只能在本文件中调用它。 const的作用:在函数f中不能修改数组元素的值,若有修改,编译时会报错。
解析:本题考查C语言基础及应用。 【问题1】 sizeof是C语言提供的一个关键字,sizeof(x)用于计算为x分配的字节数,其结果与系统或编译器相关。若x是数组名时,用于计算整个数组所占用存储空间的字节数;若x是指针,则无论其指向的目标数据是什么类型,x所占用的存储空间大小都相同(在同一系统或编译环境中);若x是结构体变量或类型,则需要根据系统规定的对齐要求来计算为x所分配空间的字节数。 根据说明,系统为每个字符型数据分配1个字节,为每个整型(int)数据分配4个字节,为每个指针分配4个字节,那么sizeof(int)、sizeof(unsigned int)是计算整型数据和无符号整型数据的存储空间大小,sizeof(arr)是计算数组arr的字节数,它们的值分别为4、4和20。 sizeof(char)计算一个字符数据所占用的字节数,根据说明应为1。sizeof(mystr)计算为字符数组mystr分配的空间大小,该数组的大小由字符串"JustAtest\n"决定,该字符串的长度为10,还有一个串尾结束标志字符'/0',因此sizeof(mystr)的值为11。 ptr是指向字符数组mystr的指针,显然sizeof(ptr)的结果为4。由于*ptr指向了一个字符数据,因此sizeof(*ptr)的结果为1,函数strlen(ptr)计算ptr所指字符串的长度,结果为10。 【问题2】 在C语言中,const关键字的一个作用是限定一个变量的值不能被改变,使用const可以在一定程度上提高程序的安全性和可靠性。 const int size=10; 或 int const size=10; 以上代码都可以定义一个“只读”型的整型常量size并将其值初始化为10。 当const用于修饰指针时,常见的情形如下: (1)const修饰的是指针所指向的对象,该对象不可改变,指针变量可改变。 const int *p; //或 int const *p; (2)const修饰的是指针,该指针变量不可改变,其指向的对象可改变。 int *const p; (3)const修饰的是指针以及指针所指向的对象,都不可改变。 const int *const p; 【问题3】 关键字static用于修饰函数中的局部变量时,是通知编译器将该变量的存储空间安排在全局存储区,这样在下一次调用函数时还保留上一次对该变量的修改结果。 当一个源程序由多个源文件组成时,用static修饰的全局变量和函数,其作用域为当前文件,对其他源文件不可见,即它们不能被其他源文件引用或调用。 当函数的形参用const修饰时,在函数体内部不能被修改。
3.【说明】为了实现单链表的操作,实现某个系统开发,进行了如下的编程设计:
已知包含头结点(不存储元素)的单链表的元素已经按照非递减方式排序,函数ccompress(NODE *head)的功能是去掉其中重复的元素,使得链表中的元素互不相同。处理过程中,当元素重复出现时,保留元素第一次出现所在的结点。 图(a)、(b)是经函数ccompress()处理前后的链表结构示例图。
添加图片注释,不超过 140 字(可选)
链表的结点类型定义如下: typedef struct Node { int data; struct Node *next; } NODE; 【C代码】 void ccompress(NODE *head) { NODE *ptr,*q; ptr = (1) ; // 取得首结点的指针 while ( (2) && ptr -> next) { //判断ptr和ptr的下一个结点是否为空 q = ptr -> next; while(q && (3) ) { //处理重复元素 (4) = q -> next; //存在重复元素时删除q所指结点 } (5) = ptr -> next; }/* end of while */ }/* end of compress */
答案:
(1)head->next (2)ptr (3)ptr->data==q->data (4)ptr->next (5)ptr
解析:本题主要考查对带头结点的单链表的操作。 (1)head->next。取带头结点的链表中的第一个结点,即头结点的下一个结点。 (2)ptr。判断ptr结点及其后一个结点是否都不为空。 (3)ptr->data==q->data。比较两个结点的值是否相同。 (4)ptr->next。如果两个结点相同,则将后一个结点移除,即删除q结点,用ptr->next= q->next语句删除。 (5)ptr。继续处理下一个结点。
4.【说明】规定整型数组a中的元素取值范围为[0,N),函数usrSort( int n, int a[] )对非负整型数组a的前n个元素进行计数排序。排序时,用temp_arr[i]表示i在数组a中出现的次数, 因此可以从0开始按顺序统计每个非负整数在a中的出现次数,然后对这些非负整数按照从小到大的顺序,结合其出现次数依次排列。 例如,对含有10个元素{0,8,5,2,0,1,4,2,0,1}的数组a[]排序时,先计算出有3个0、2 个1、2个2、1个4、1个5和1个8,然后可确定排序后a的内容为{0,0,0,1,1,2,2,4,5,8}。 下面代码中用到的memset函数的原型如下,其功能是将p所指内存区的n个字节都设置为ch的值。 void*memset (void *p, int ch, size_t n);
【C代码】 #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 101 void printArr(int a[],int n); void usrSort(int n,int a[]); int main() { int a[10]={0,8,5,2,0,1,4,2,0,1}; printArr (a,sizeof(a)/sizeof(int)); ( 1 ) ; //调用usrSort()对数组a进行升序排序 printArr ( a,sizeof(a)/sizeof(int) ); return 0; } void printArr (int a[],int n) { int i; for(i=0;i<n;i++) printf("%d ", a[i]); printf("\n"); } void usrSort(int n, int a[]) { int i,k; int *temp_arr; //用temp_arr[i]表示i在a中出现的次数 temp_arr=(int *)malloc(N*sizeof(int) ); if(!temp_arr) return; //将所申请并由temp_arr指向的内存区域清零 memset( (2) ); for(i=0;i<n;i++) temp_arr[ ( 3 ) ]++; k=0; for(i=0;i<N;i++){ int cnt; //cnt表示i在数组a中的出现次数 ( 4 ) ; while(cnt>0){ a[k]=i; //将i放入数组a的适当位置 ( 5 ) ; cnt--; } } free(temp_arr); }
【问题1】(5分) 变量存储类型是指数据在内存中存储的方法,即确定所定义的变量在内存中的存储位置,也确定了变量的作用域和生存期,内部变量有3种存储类型。假设有一个内部整型变量aa,请按不同存储类型给出相应的变量声明。 【问题2】(10分) 请补充完成程序中的(1)~(5)空内容。
答案:
【问题1】 自动内部变量:int aa;或auto int aa; 寄存器内部变量:register int aa;或register aa; 静志内部变量:static int aa; 【问题2】 (1) usrSort(10,a)或等效形式,a可替换为&a,&a[0]。 (2) temp_arr,0,N*sizeof(int)或等效形式,其中N和sizeof(int)可替换为101、4。 (3) a[i]或*(a+i)或等效形式 (4) cnt = temp_arr[i]或cnt= *(temp_arr+i)或等效形式 (5)k++或++k或k=k+1或k+=1或等效形式
解析:本题考查C语言的基本概念和编程方面的基本知识。 【问题1】 变量存储类型是指数据在内存中存储的方法,即确定所定义的变量在内存中的存储位置,也确定了变量的作用域和生存期,内部变量存储类型有3种,分别是:自动内部变量、寄存器内部变量、静态内部变量。 自动(auto)存储型变量又称自动变量,它是最常用的一种变量的存储类型,在函数内部或复合语句内部定义的局部变量(或称为内部变量)。只要存储类型是缺省的,均为自动变量。它的特点是其生命期域定义它的函数或复合语句的执行期同长,且有效范围仅在定义它的函数或复合语句内。 寄存器(register)存储型变量一般存储在计算机CPU的通用寄存器中,因而定义的这种类型变量存取速度快,适合于频繁使用的变量,可加快程序的运行速度,由于CPU中通用寄存器的数目有限,且每次可供C语言使用的通用寄存器数更有限,因而在程序中不宜大量使用这种存储类型的变量,以二三个为宜,当然超过可用的寄存器数,也不会出错,编译程序将会将超过可用寄存器数的寄存器型变量当作auto变量处理。一般将最频繁使用的变量定义成寄存器型变量。 静态(static)存储型变量是分配在存储器中C程序占据的数据段内,对运行的C程序而言,这是一个程序所用的固定内存区域,因而静态变量的存储地址在整个程序的运行执行期间均保留,不会被别的变量占据。静态变量可以定义成全局变量或局部变量,当定义成全局变量时,它在定义它的整个程序执行期间均存在,其原来的存储位置不会变化。当定义成局部变量时,虽然在定义它的函数内或复合语句中有效,但在执行完该函数或复合语句后,静态变量最后取得的值仍然保存,不会消失,因为它所占的存储地址不会被别的变量占用,这样,当程序再次调用该函数或执行该复合语句时,该静态变量当前值就是再次进入该函数或执行该复合语句的初始值。 假设有一个内部整型变量aa,按不同存储类型的变量声明如下: a)自动内部变量:int aa;或auto int aa; b)寄存器内部变量:register int aa;或register aa; c)静态内部变量:static int aa; 【问题2】 根据空(1)所在语句的注释,明确是对函数usrSort进行调用。usrSort的原型声明为“void usrSort(int n, int a[])",第一个参数表示需要排序的元素个数,第二个参数表示对哪个数组进行排序,题目中,需要对含有10个元素的数组进行排序,因此 空(1)应填入“usrSort(10,a)” 或其等效形式 。注意:第二个参数需要传入的数组(数组首地址),用数组名数组名或下标为0的数组元素取地址都可以,因此。 空(2)所在语句是调用memset对申请的存储区域进行初始化。根据注释,要求将 temp_arr指向的内存区域清零,根据声明memset时的定义, void*memset (void *p, int ch, size_t n); , 此处需要对temp_arr 所指向的空间区域的元素值都设置为0,而总king就可以结合语句:temp_arr=(int *)malloc(N*sizeof(int) );,表示temp_arr占用空间为N*sizeof(int),可知函数调用为memset ( temp_arr , 0 , N * sizeof ( int ) ) 。 空(3)所在的循环语句遍历数组a[]的所有元素,将元素a[i]作为temp_arr的下标, 从而使得temp_arr[a[i]]表示了a[i]表示的值在数组a中出现的次数。例如:数组a中函数元素1,则需要temp_arr[1]的值+1, 数组a中函数元素5,则需要temp_arr[5]的值+1。 空(4)、(5)主要是通过temp_arr中的元素取值情况来对数组a中元素进行重排,假设tem_arr[0]=3,则表示0元素出现了3次。首先用cnt保留元素出现的次数, 可知空(4)处应设置cnt的初始值,为“temp_arr[i]”。 当cnt>0时,表示元素i出现的次数超过了1次,需要进行循环填入, 每在数组中放入1个i元素后,cnt自减(表明还需要放置的次数要减1),而k需要自增(表明元素放置位置要往后一个),以给出下一个i要放入的数组位置,因此空(5)处应填入“k++”或其等效形式。