1、温度是表示物体或环境冷热程度的一种物理量,而温度传感器是一种能将温度变化转换成电量变化的元器件。由于二极管制造工艺的特殊性,我们可以利用二极管的伏安特性来测量环境的温度,它的伏安特性如下图众所周知,将PN结用外壳封装起来,并加上电极引线就构成了半导体二极管,即所谓的二极管。由P区引出的电极为阳极,由N区引出的电极为阴极,如下图所示温度对二极管的性能有较大的影响,温度升高时,二极管的正向压降将减小,每增加1C,正向压降减小约2mV,因此可以使用这一特性来测量环境温度。 由半导体理论可以得出,PN结所加端电压u与流过它的电流i的关系为:其中, Is为反向饱和电流,对于硅材料来说,Is约为10pA;
2、 q为电子的电量,q=1.6*10的-9次方库伦; k是玻耳茨曼常数,k=1.38*10的-23次方J/K; T为绝对温度, kT/q可以用UT来代替, 常温下,即T=300K时,UT约为26mV。 对于足够大的电压,二极管方程可以近似写成 那么,二极管两端的电压可以推导出为:因此温度的公式为: 3.器件的选择和芯片的介绍本系统采用了ST公司和高性能微控制器STM32F130ZET6,该微控制器具有512K ROM以及62K RAM 足以满足该项目的需求。本系统使用到的模块有:ENC28J60模块,0.96OLED模块,SD卡模块,以及2个无线模块和USB-TTL模块。为了满足这些模块的供电需
3、求另外自己用洞洞板做了AMS1117的稳压模块,以及采用德州仪器公司的TPS7333稳压芯片制作了稳压模块为无线模块提供稳定可靠的电源使数据的发送和接收更加稳定。AMS1117系列稳压芯片有可调版与多种固定电压版,设计用于提供1A输出电流且工作压差可低至1V。在最大输出电流时,AMS1117器件的压差保证最大不超过1.3V,并随负载电流的减小而逐渐降低。本系统采用的是输出3.3v的固定电压版本。电路图如下:TPS7333是由德州仪器公司研发生产的单通道线性稳压芯片,具有单输出 LDO、500mA、固定电压 (3.3V)、集成 SVS、低静态电流,性能十分稳定,输出电压纹波低。应用电路比较简单,
4、电路如下:4.UC/OS系统移植uC/OS是一个微型的实时操作系统,包括了一个操作系统最基本的一些特性,如任务调度、任务通信、内存管理、中断管理、定时管理等。而且这是一个代码完全开放的实时操作系统,简单明了的结构和严谨的代码风格,非常适合初涉嵌入式操作系统的人士学习。很多人在学习STM32中,都想亲自移植一下uC/OS,而不是总是用别人已经移植好的。在我学习uC/OS的过程中,查找了很多资料,也看过很多关于如何移植uC/OS到STM32处理器上的教程,但都不尽人意,主要是因为是时间比较赶,无法静下心开好房学习,在一个月时间内完成STM32的学习以及UIP、文件系统的移植还是比较辛苦和困难的。1
5、.首先需要从官网上下载UC/OS的源码,并且选择STM32F103ZET6,由于官方没有公布KEIL版本的工程只有IAR版本,所以需要进行一定的修改才可用于KEIL中。UC/OS 的文件结构如下图所示:2.按照下图的文件结构搭建uC/OS工程文件结构 把LED工程所在的文件夹先改名为:STM32+UCOS 在USER文件夹下新建includes.h头文件。 按照之前给的uC/OS-II文件结构图,我们在工程的根目录下建立BSP文件夹、APP文件夹和uCOS-II文件夹。BSP文件夹 存放外设硬件驱动程序。APP文件夹 存放应用软件任务 uCOS-II文件夹 uC/OS-II的相关代码 把USE
6、R文件夹下的led.h 和led.c文件剪切到BSP文件夹里。在BSP文件夹里新建BSP.c和BSP.h文件。 在APP文件夹下建立app.h、app.c和app_cfg.h文件。拷贝uC/OS-II源代码附件那里的MicriumSoftwareEvalBoardsST STM32F103ZE-SKIAROS-Probe-LCDos_cfg.h到此目录。 把uC/OS-II源代码附件那里的MicriumSoftwareuCOS-II下的Source文件夹复制到工程里刚才新建的uCOS-II文件夹里。把MicriumSoftwareuCOS-IIPortsarm-cortex-m3Generic
7、IAR下的文件复制到工程uCOS-II文件夹中新建的Ports文件夹里。复制后,选中全部文件,右键属性去掉只读属性确定。如下图添加include path3.配置uC/OS-II a. 修改os_cfg.h: 首先禁用信号量、互斥信号量、邮箱、队列、信号量集、定时器、内存管理,关闭调试模式:#define OS_FLAG_EN 0 /禁用信号量集 #define OS_MBOX_EN 0 /禁用邮箱 #define OS_MEM_EN 0 /禁用内存管理 #define OS_MUTEX_EN 0 /禁用互斥信号量 #define OS_Q_EN 0 /禁用队列 #define OS_SEM_
8、EN 0 /禁用信号量 #define OS_TMR_EN 0 /禁用定时器 #define OS_DEBUG_EN 0 /禁用调试 b. 修改os_cpu.h 注释掉这三行void OS_CPU_SysTickHandler(void);void OS_CPU_SysTickInit(void);INT32U OS_CPU_SysTickClkFreq(void);c. 修改os_cpu_c.c 把 OS_CPU_SysTickHandler(), OS_CPU_SysTickInit()及 如下图的文件注释掉 d. 修改 os_cpu_a.asm 由于编译器的原因要将下面的PUBIC改为E
9、XPORT:PUBLIC OS_CPU_SR_Save ; Functions declared in this file PUBLIC OS_CPU_SR_Restore PUBLIC OSStartHighRdy PUBLIC OSCtxSw PUBLIC OSIntCtxSw PUBLIC OS_CPU_PendSVHandler e. 修改os_dbg.c 将#define OS_COMPILER_OPT _root 改为#define OS_COMPILER_OPT / _root 修改startup_stm32f10x_hd.s 因为本次移植是使用标准外设库CMSIS中startu
10、p_stm32f10x_hd.s作为启动文件的,还没有设置 OS_CPU_SysTickHandler。而startup_stm32f10x_hd.s文件中,PendSV 中断向量名为PendSV_Handler,因此只需把所有出现PendSV_Handler的地方替换成OS_CPU_PendSVHandler即可。编写includes.h #ifndef _INCLUDES_H_ #define _INCLUDES_H_ #include stm32f10x.hstm32f10x_rcc.h /SysTick定时器相关 ucos_ii.h /uC/OS-II系统函数头文件 BSP.h /与开
11、发板相关的函数 app.h /用户任务函数 led.h /LED驱动函数 #endif /_INCLUDES_H_ 编写BSP .cincludes.hvoid BSP_Init(void) SystemInit(); /* 配置系统时钟为72M */ SysTick_init(); /* 初始化并使能SysTick定时器 */ LED_GPIO_Config(); /* LED 端口初始化 */ void SysTick_init(void) SysTick_Config(SystemFrequency/OS_TICKS_PER_SEC);/初始化并使能SysTick定时器 Bsp.h#if
12、ndef _BSP_H #define _BSP_H void SysTick_init(void);void BSP_Init(void);#endif / _BSP_H 编写main.cstatic OS_STK startup_task_stkSTARTUP_TASK_STK_SIZE; /定义栈 int main(void) BSP_Init();OSInit();OSTaskCreate(Task_LED,(void *)0, &startup_task_stkSTARTUP_TASK_STK_SIZE-1, STARTUP_TASK_PRIO);OSStart();return 0
13、;至此,UC/OS的移植已经完成,运行多任务只需在APP.C里修改即可。限于篇幅,一下不再赘述,详情请看源码。5.文件系统的移植与文件系统基本函数的功能1) SDIO配置与SD卡实现:a. SDIO接线如下图所示:b. SDIO时钟设置:SDIO_CK时钟是通过PC12引脚连接到SD卡的,是SDIO接口与SD卡用于同步的时钟。SDIO选配器挂载到AHB总线上,通过HCLK二分频输入到适配器得到SDIO_CK的时钟,这时SDIO_CK = HCLK/(2+CLKDIV)。其中CLKDIV是SDIO_CLK(寄存器)中的CLKDIV位。另外,SDIO_CK也可以由SDIOCLK通过设置bypass
14、模式直接得到,这时SDIO_CK = SDIOCLK=HCLK。可以通过以下函数进行时钟配置SDIO_Init(&SDIO_InitStructure);对SD卡的操作一般是大吞吐量的数据传输,所以采用DMA来提高效率,SDIO采用的是DMA2中的通道4。在数据传输的时候SDIO可向DMA发出请求。c.SDIO协议驱动声明:由于原来没有了解过SD协议,又看到SDIO的驱动有2000多行,时间紧迫,感觉无从下手。故采用ST公司官方驱动。以下简要介绍所用到的函数的功能SDIO_SendCommand(&SDIO_CmdInitStructure); /配置和发送命令SDIO通过CMD接收到响应后,
15、硬件去除头尾的信息,把command index 保存到SDIO_RESPCMD寄存器,把argument field内容保存存储到SDIO_RESPx寄存器中。这两个值可以分别通过下面的库函数得到。SDIO_GetCommandResponse(); /卡返回接收到的命令 SDIO_GetResponse(SDIO_RESP1); /卡返回的argument field内容 d.SDIO_Init()函数:1) 用 GPIO_Configuration()进行SDIO的端口底层配置 2) 分别调用了SD_PowerON()和SD_InitializeCards()函数,这两个函数共同实现了上
16、面提到的卡检测、识别流程。3) 调用SDIO_Init(&SDIO_InitStructure)库函数配置SDIO的时钟,数据线宽度,硬件流(在读写数据的时候,开启硬件流是和很必要的,可以减少出错) 4) 调用SD_GetCardInfo(&SDCardInfo)获取sd卡的CSD寄存器中的内容,在main函数里输出到串口的数据就是这个时候从卡读取得到的。5) 调用SD_SelectDeselect()选定后面即将要操作的卡。6) 调用SD_EnableWideBusOperation(SDIO_BusWide_4b)开启4bit数据线模式 如果SD_Init()函数能够执行完整个流程,并且返
17、回值是SD_OK的话则说明初始化成功,就可以开始进行擦除、读写的操作了。下面进入SD_PowerON()函数,分析完这个函数大家就能了解SDIO如何接收、发送命令了。e.SDIOIint()中使用的函数:SD_PowerON 函数:确保SD卡的工作电压和配置控制时钟 SD_InitializeCards:初始化所有的卡或者单个卡进入就绪状态 2)FATFS文件系统的移植FATFS是面向小型嵌入式系统的一种通用的FAT文件系统。FATFS完全是由AISI C语言编写并且完全独立于底层的I/O介质。因此它可以很容易地不加修改地移植到其他的处理器当中,如8051、PIC、AVR、SH、Z80、H8、
18、ARM等。FATFS支持FAT12、FAT16、FAT32等格式,利用前面写好的SDIO驱动,把FATFS文件系统代码移植到工程之中,就可以利用文件系统的各种函数,对已格式化的SD卡进行读写文件了。首先从官网下载FATFS源码,然后解压到工程文件中,并添加到工程中下面对FATFS的文件做说明:integer.h:是一些数值类型定义 diskio.c : 底层磁盘的操作函数,函数需要用户自己实现 ff.c : 独立于底层介质操作文件的函数,完全由ANSI C编写 cc936.c :简体中文支持所需要添加的文件,包含了简体中文的GBK和转换函数。ffconf.h:这个头文件包含了对文件系统的各种配
19、置,如需要支持简体中文要把_CODE_PAGE 的宏改成936并把上面的cc936.c文件加入到工程之中 移植过程中要修改的文件1、将integer.h中有关BOOL的那句注释掉2、在ff.c文件的开头重新定义一个布尔变量,取名为 bool,与stm32f10x.h中的名字一样:同时在 ff.c的第585行做如下修改:文件系统移植成功!下面介绍文件系统中的几个底层函数:a. 文件系统初始化函数接口的实现DSTATUS disk_initialize ( BYTE drv /* Physical drive nmuber (0.) */) SD_Error Status; /* Supports
20、 only single drive */ if (drv) return STA_NOINIT; /*- SD Init - */ Status = SD_Init(); if (Status!=SD_OK ) else return RES_OK;这个函数调用了SDIO的SD_Init()函数,返回成功或失败的参数,当文件系统调用到这个函数的时候,实际上是调用了SD_Init()对SD卡进行初始化。b. 扇区读取函数的实现:DRESULT disk_read ( BYTE drv, /* Physical drive nmuber (0.) */ BYTE *buff, /* Data b
21、uffer to store read data */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to read (1.255) */ if (count 1) SD_ReadMultiBlocks(buff, sector*BLOCK_SIZE, BLOCK_SIZE, count); /* Check if the Transfer is finished */ SD_WaitReadOperation(); /循环查询dma传输是否结束 /* Wait until end of DMA
22、 transfer */ while(SD_GetStatus() != SD_TRANSFER_OK); SD_ReadBlock(buff, sector*BLOCK_SIZE, BLOCK_SIZE); return RES_OK;此函数分为了2个部分,分为单块读取和多块读取数据,因为使用SD_ReadMultiBlocks比SD_ReadBlock(速度要快所以加入了一个判断函数来区分以增加系统的效率。由于文件系统都是以块(512字节)为单位读写的所以只要提供512字节或者512*N字节的SD卡驱动即可。c. 扇区写入函数的实现:DRESULT disk_write ( BYTE dr
23、v, /* Physical drive nmuber (0.) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to write (1.255) */ SD_WriteMultiBlocks(uint8_t *)buff, sector*BLOCK_SIZE, BLOCK_SIZE, count); /* Check if the Transfer is finished */ SD_WaitWriteOperation(); /等待dma传输结束 /等待sdio到sd卡传输结束 SD_WriteBlock(uint8_t *)buff,sector*BLOCK_SIZE, BLOCK_SIZE); SD_WaitWriteOperation();#endif /* _READONLY */*-*/* Miscellaneous Functions */DRESULT disk_ioctl (
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1