当前位置:文档之家› uCOSII的内核移植

uCOSII的内核移植

uCOSII的内核移植
uCOSII的内核移植

河海大学计算机及信息工程学院(常州)课程设计报告

题目uCOSII的内核移植

专业、学号0962910212 电科

学生姓名葛彦源

指导教师金纪东

完成时间2012年6月20

嵌入式系统是当今非常热门的研究领域,早期多以单片机为核心,应用领域非常广泛.但单片机系统功能比较简单,速度较慢,难以适应现代技术的快速发展.随着现场可编程逻辑阵列技术的日益成熟,基于片上可编程系统的嵌入式处理器越来越多地受到人们的关注.特别是Altera公司推出的Nios II嵌入式处理器软核,通过软件编程的方法可灵活地实现嵌入式的功能,并且针对进行性能优化,可大大提高系统性能.它还具有片上调试功能,便于系统的设计和调试.随着芯片技术的发展,SOPC成为嵌入式系统设计的一个发展趋势,不同于桌面操作系统,嵌入式操作系统需根据特定的嵌入式应用及不同的处理器而进行移植和裁剪。

本次课设主要研究了嵌入式操作系统中应用较为广泛的、源代码开放的UCOSII在基于目前应用非常广泛的ARM7处理器体系结构上的移植,并在此基础上实现了简单的多任务应用程序的操作。

摘要 (2)

一课程设计 (4)

1.1课程设计目标及其预期效果 (4)

1.2实现方法 (4)

二系统设计 (5)

2.1UCOSII操作系统的简介 (5)

2.2S3C44B0X简介 (5)

2.3UCOSII的内核结构 (6)

2.4可移植性分析 (7)

三实验结果及分析 (8)

3.1UCOSII移植及测试 (8)

3.1.1移植过程 (8)

3.1.2测试过程 (9)

3.2UCOSII测试结果 (9)

3.2.1建立工程 (9)

3.2.2 ADS1.2下仿真、调试 (10)

四实验结论 (12)

心得体会 (12)

参考文献 (13)

附录 (13)

一课程设计

1.1课程设计目标及其预期效果

1. 移植UCOSII到三星的S3C44B0X(或者LPC210X )ARM7TDMI处理器上

2.编写多任务应用程序:一个熄灭D7、D8灯的任务,一个点亮D7熄灭D8的任务,一个熄灭D7点亮D8的任务,三个任务轮流输出。

1.2实现方法

首先给系统建立三个任务,其内容分别为D7亮,D8灭,D7灭,D8亮,D7,D8全灭。和通过程序设定一个变量flag,首先将D7点亮,并将flag的值设为0,并跳转到下一个任务,以此类推已达到循环目的。我们创建三个不同的任务,每个任务都有一个相对应的信号量,在系统开始运作之初,我们发送一个信号量,让其中一个任务接收到而开始工作,而在每个任务的最后会发送另外一个任务所相对应的信号量,当另一个任务接收到时就开始运行。由此通过三个信号量发送与接收的循环往复,而实现三个任务的循环执行。

UCOSII任务状态转换

二系统设计

2.1 UCOSII操作系统的简介

UCOSII是源码公开的实时操作系统,是一个自由操作系统。程序开发人员可以改写源代码,使之符合自己的要求,裁减掉不需要的部分,使操作系统变得小巧、灵活、并且能满足用户特定操作系统的需要。为了提高系统的实时能力,UCOSII可以将一个复杂的应用划分为多个相互独立的任务,并根据任务的重要性来分配优先级。任务的调度完全由UCOSII的实时内核完成,主要包括任务的状态管理、选择最高优先级的任务、执行任务和撤销任务等,UCOSII内核还负责CPU 时间分配,CPU 时间总是优先分配给中断事件,其次是任务队列中当前优先级最高的任务,不同任务间的通信可以通过UCOSII提供的信号量、邮箱、信息队列等机制完成,他的绝大部分代码是用 C 语言编写的,可移植性强,因此1997 年以后,在国际上逐渐被广泛采用。

2.2S3C44B0X简介

Samsung公司推出的16/32位RISC处理器S44B0X为手持设备和一般类型应用提供了高性价比和高性能的微控制器解决方案。为了降低成本,S44B0X提供了丰富的内置部件:8KB Cache,可选的内部SRAM,LCD控制器,带自动握手的2通道UART,4通道DMA,系统管理器(片选FP/EDO/SDRAM控制器),带PWM功能的5通道定时器,I/O端口,RTC,8通道10为ADC,IIC总线接口,IIS总线接口,同步SIO接口和PLL倍频器。S44B0X采ARM7TDMI内核,0.25um工艺的CMOS标准宏单元和存储编译器。它低功耗,精简,出色和全静态的设计特别适用于成本和

功耗敏感的应用。同样S44B0X 还采用了一种新的总线结构,即SAMBAII(SAMSUNG ARM CPU 嵌入式微处理器总线结构)。

S44B0X 的显著特性时它的CPU 核,是由ARM 公司设计的16、32位的ARM7TDMI RISC 处理器(66MHZ ).ARM7TDMI 体系结构的特点是它集成了Thumb 代码压缩器,一个片上ICE 断点调试支持和一个32位的硬件乘法器。

S44B0X 提供全面的,通用的片上外设,大大减少了系统电路中除处理器以外的元器件配置,从而最小化系统的成本。

LED 接口

基于ARM 架构的32位微处理器

Samsung

S3C44BOX IBM 线性

Flash(BIOS)8MBSDRAM 16MB 非线性

Flash(硬盘)USB 接口

两个RS-232串行通信接口

JTAG 调试端口

基于S3C44B0X 的嵌入式硬件平台

2.3 UCOSII 的内核结构

UCOSII 的移植,首先得来看看它的内核结构[2],

现在介绍各个方框内的部分。从上往下看,可以看到应用程序在整个UCOSII 的构架的最上方。这点也很容易理解,因为UCOSII作为一个很优秀的嵌入式操作系统,它最基础的功能就在底层驱动支持下屏蔽硬件的差异性,来为用户提供一个不需要考虑硬件的多任务平台。因此和其他的操作系统一样,用户程序都是建立在UCOSII内核基础之上的。这样非常方便应用程序的编写。

中间层左边方框内的这些代码是与处理器及其他硬件都无关的代码。可以看到,这些代码占了整个UCOSII的绝大部分。作为嵌入式操作系统,易于移植是一个优秀操作系统必不可少的特性之一。为了使UCOSII易于移植,它的创始人花费了大量的心血,力求与硬件相关的代码部分占整个系统内核的比例降到最小。

中间层右边方框里列出的实际上是两个头文件。OS_CFG.H是为了实现UCOSII内核功能的裁剪。通过配置这个头文件,UCOSII可以方便的实现裁剪,

以适应不同的嵌入式系统。而INCLUDES.H则包含了所有的头文件,这样在应用

程序包含头文件时只需将此头文件包括进去就能包含UCOSII所有的头文件了。

最下面的一个方框列出的是与处理器相关的代码,这部分是移植的主角,重头戏都在这里面。在这一部分里,主要是一些和处理器相关的函数或者宏定义。整个移植的代码都在这几个文件中,大概几百行。移植需要几小时到几星期不等,主要取决于对UCOSII和目标处理器的了解程度。

2.4可移植性分析

UCOSII核心代码很小,程序开发人员要把他移植到自己的目标板中只需做少量的工作。虽然UCOSII大部分源代码是用C语言写的,但是完成和处理器有关的代码时,还是用汇编语言来实现的。从资料可以知道,UCOSII的移植的主要工作是修改与处理器相关部分的代码,他们集中在3个文件中,其中,OS_CPU.H包含与处理器相关的常量、宏和结构体的定义;OS_CPU_C.C和OS_CPU_ASM中定义了用于底层的任务切换,退出中断服务程序,在CPU级屏蔽中断、打开中断、对任务栈初始化以及时钟的中断服务程序的函数等,为了使应用程序运行于UCOSII上,还要相应地修改应用中使用的硬件和设备驱动。

三实验结果及分析

3.1UCOSII移植及测试

3.1.1移植过程

要把UCOSII移植到ARM7TDMI处理器上,必须写三个文件,这三个文件都是与处理器的架构紧密相关的,它们是OS_CPU.h,OS_CPU_A.s,OS_CPU_C.c。它们的作用是把UCOSII操作系统紧紧的附着在ARM处理器上,实现软件与硬件的协同。

1)OS_CPU.h:

a. 把编译器类型数据重定义为UCOS-II内核所用的数据类型;

b. 编写相应ADS或SDT编译器的开关中断的函数;

c. 定义单个堆栈的数据宽度;

d.定义微处理器的堆栈的增长方向;

2)OS_CPU_C.c:

文件中主要包括10个函数,其中一个是任务堆栈初始化函数,其他九个为操作系统扩展的钩子函数。在OSTaskCreate()和OSTaskCreateExt()中,通过调用任务堆栈初始化函数OSTaskStkInit()来初始化任务的堆栈结构,初始完毕后,堆栈看起来就像刚发生过中断并将所有的寄存器内容保存到该任务堆栈中的情形一样。

3)OS_CPU_A.s:

文件中主要包括5个函数: OSStartHighRdy()负责启动最高优先级任务;OSIntCtxSw ()负责中断中的任务切换;OSCtxSw()负责任务切换;OSCPUSaveSR()负责保存中断前的寄存器状态;OSCPURestoreSR()负责中断完成后,恢复中断前的状态。

主体移植过程:

1).设置与处理器及编译器相关的代码[OS_CPU.H];

2).用C语言实现与处理器任务相关的函数[OS_CPU_C.C];

3).处理器相关部分汇编实现。

3.1.2测试过程

做完移植工作以后,就要测试移植是否正确,这其实是移植过程的最后一步,应该首先不加任何用代码来测试移植好的UCOSII,即应该首先测试内核自身的运行状况,这样做的目的是如果有些部分未能正常工作,那就是移植本身的问题,而不是应用代码产生的问题,主要分为以下几个步骤来进行移植的测试:

首先,必须了解处理器所使用的编译器系统,这个步骤取决于使用的编译器,在这期间是无代码的测试,其次,要验证OSTaskStkInit ()和OSStartHighRdy ()函数,在OS_CFG.H 文件中设置OS_TASK_STAT_EN

为 0 ,只让一个空闲任务OS_TaskIdle ()运行,检查是否出错,然后需要验证任务级切换OSCtxSw ()函数,在测试任务TaskTest ()中加入OSTimeDly ()函数,OSTimeDly ()函数接着调用OS_Sched (),OS_Sched ()调用汇编语言编写的函数OSCtxSw ()函数,如果是正确配置了SWI,CPU 就会开始执行OSCtxSw (),最后,需要验证OSIntCtxSw ()和OSTickISR()函数。

当上述的这些测试步骤都成功后,可以尝试运行一些具体的任务,按照由简到繁的过程不断使测试变得复杂,来进一步验证内核的稳定性和系统性能。

3.2UCOSII测试结果

3.2.1建立工程

我们在ADS编译器中中进行了UCOSII系统移植并编写了应用程序后,得到如图所示的目录,Application/INC目录下存放的是操作系统下的应用程序的头文件,Application/SRC目录下存放的是操作系统的应用程序;Startup44b0/INC 目录下存放的是ARM的启动代码和CPU板初始化程序的头文件,Starup44b0/SRC目录下存放的是ARM的启动源代码文件44binit.s,库文件44blib.c,CPU板的初始化文件target.c,在这里我们没有串口初始化,主要是针对后面章节里有专门讲述如何填加串口驱动,如何利用串口收发的缘故。在UCOSII/CPU目录下存放的是操作系统的移植文件,UCOSII/INC目录下存放的是和应用任务相关的头文件,UCOSII/SRC目录下存放的是UCOSII操作系统的源代码,它们是由Ucos_II.C文件嵌进来的。在UCOSII的正常运行之前,还必须进行硬件系统的初始化,这也就是需要文件夹Startup44b0的理由。

3.2.2 ADS1.2下仿真、调试

在ADS1.2下进行仿真调试,首先要连接wigger调试电缆,然后,给实验箱上电,打开H-JTAG程序,如图1,自动连接实验箱(或点击第二个按钮detect target进行连接)。正确连接后出现图2的界面。

图5

图1

图2

如不能正确连接请检查电源是否打开和连线是否正确。当连上仿真器后,打开调试软件AXD Debugger,如图3。点击File|load image 加载文件.axf。

图3

最后在实验箱上得到测试结果:一开始熄灭D7、D8灯,然后点亮D7熄灭D8的,最后熄灭D7点亮D8,并按此顺序循环执行。

四实验结论

UCOSII作为一个嵌入式实时操作系统,自1992年以来,因其源代码的完全公开和优越性能,已为众多的爱好者和开发人员所了解并得到了广泛应用。UCOSII是一个占先式内核,执行时间可确定(即函数的调用与服务的时间是可知的,不依赖于应用程序的大小),目前最多支持64个任务(8个为系统保留),总是执行处于就绪态的优先级最高的任务。目前,51系列及其扩展型单片机仍在单片机应用系统占较大比重,因而详细介绍UCOSII在AT89C51上的移植实现过程,解决移植过程中出现的问题,有很大的实用意义。对于UCOSII在 ARM7 上移植,针对不同的处理器还需要作适当的修改, RTOS 是当今嵌入式应用的热点,应用 RTOS ,可以提高产品的可靠性,降低研发周期,其中μC/OS- Ⅱ具有很好的实时性和很小的代码量,占用空间少,执行效率高,移植方法相对简单,因此掌握μC/OS- Ⅱ的移植方法是相当重要的。

心得体会

本次课程设计中我们遇到过很多问题,也因此学到了许多东西。由于我们在课堂上学习到的东西,在此次课设中用处不大。特别是关于嵌入式操作系统方面的知识,我们更是缺乏。于是我们便借助于网络以及图书馆的书籍资料查阅,最终对内核移植的过程,以及uCOSII这个抢占式多任务操作系统的任务切换的特点等有了一个大致的了解。我们先搭建了整体的项目框架,然后不断往每个框架里面填充代码。关于UCOSII内核移植的3个主要文件,我们是从网上搜索得来了;关于开发版部分的程序是我们结合课堂上做过的实验以及资料完成的;UCOSII的应用程序的内容是我们根据以往实验内容,再通过编译器不断调试完善的。后来刚开始进行硬件时,只是不能达到预计的现象。但在我们不懈的努力,加之与其它小组进行讨论,终于达到了实验目的。

本次课设让我懂得了很多书本上所学不到的知识,锻炼了我们的动手能力。更让我们明白了协同合作的重要性。今天我们要多多实践,将理论与实践结合,为将来就业打下坚实的基础。

参考文献

[1]王勇,何立民.嵌入式系统原理与设计.杭州:浙江大学大学出版社,2007.

[2]邵贝贝等译.嵌入式实时操作系统uCOSII(第2版).北京:北京航空航天大

学出版社,2003年5月.

[3]王田苗.嵌入式系统设计与实例开发[M].北京:清华大学出版社,2003.1-10

[4]杨宗德.uCOSII标准教程.北京:人民邮电出版社,2007.

附录

小组成员:0962910212 葛彦源

0962910234 庄文龙

STM32学习笔记

输入模式初始化GPIOE2,3,4 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PORTA,PORTE时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); ③PE.2.3.4端口配置:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; ④设置成(上拉)输入:GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; ⑤GPIO_Init(GPIOE, &GPIO_InitStructure); 输出模式初始化 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PB,PE端口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); ③3LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; ④设置(推挽)输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ⑤设置IO口速度为50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ⑥说明初始化哪个端口GPIO_Init(GPIOB, &GPIO_InitStructure); 在LED灯试验中初始为高电平灭GPIO_SetBits(GPIOB,GPIO_Pin_5); 再初始化相同发输出模式时③④⑤可省略例如(经实验初始化恰好为不同IO口相同IO序号③可省略,应该不规范吧) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数; 2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。 3,头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。 4,他并不是C自带的,可以不用。 5,调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h 这个头文件。

STM32学习笔记_STM32F103ZET6

STM32F103 系列芯片的系统架构: 系统结构: 在每一次复位以后,所有除SRAM 和FLITF 以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR 来打开该外设的时钟。

GPIO 输入输出,外部中断,定时器,串口。理解了这四个外设,基本就入门了一款MCU。 时钟控制RCC: -4~16M 的外部高速晶振 -内部8MHz 的高速RC 振荡器 -内部40KHz低速RC 振荡器,看门狗时钟 -内部锁相环(PLL,倍频),一般系统时钟都是外部或者内部高速时钟经过PLL 倍频后得到 - 外部低速32.768K 的晶振,主要做RTC 时钟源

ARM存储器映像: 数据字节以小端格式存放在存储器中。一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。

存储器映像与寄存器映射: ARM 存储器映像 4GB 0X0000 00000X1FFF FFFF 0X2000 00000X3FFF FFFF 0X4000 00000X5FFF FFFF

寄存器说明: 寄存器名称 相对外设基地址的偏移值 编号 位表 读写权限 寄存器位 功能说明 使用C语言封装寄存器: 1、总线和外设基地址封装利用地址偏移 (1)定义外设基地址(Block2 首地址) (2)定义APB2总线基地址(相对外设基地址偏移固定) (3)定义GPIOX外设基地址(相对APB2总线基地址偏移固定)(4)定义GPIOX寄存器地址(相对GPIOX外设基地址偏移固定)(5)使用 C 语言指针操作寄存器进行读/写 //定义外设基地址 #define PERIPH_BASE ((unsigned int)0x40000000) 1) //定义APB2 总线基地址 #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2) //定义GPIOC 外设基地址 #define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3) //定义寄存器基地址这里以GPIOC 为例 #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4) #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04) #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08) #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C) #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10) #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14) #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18) //控制GPIOC 第0 管脚输出一个低电平5) GPIOC_BSRR = (0x01<<(16+0)); //控制GPIOC 第0 管脚输出一个高电平 GPIOC_BSRR = (0x01<<0);

stm32学习 c语言笔记

这是前段时间做彩屏显示时候遇到的难题, *(__IO uint16_t *) (Bank1_LCD_C)这个就是将后面的数据转换为地址,然后对地址单元存放数据。可如下等效: __IO uint16_t *addr; addr = (__IO uint16_t *) Bank1_LCD_C; #ifdef和#elif连用,语法和if。。。else if语句一样 推挽输出增加驱动,可以驱动LED起来 static int count=0 count++ 这个语句中,count仅仅被初始化一次 以后加加一次期中的值就不会变化了 SysTick_CTRL(控制和状态寄存器) SysTick_LOAD(重装载寄存器) SysTick_VAL(当前值寄存器) SysTick_CALIB(校准值寄存器)

TFT经验:弄多大的相片,必须先把那个相片的尺寸改掉,再去取模,才可以,要不会有重影的嘿嘿嘿嘿 VBAT 是电池供电的引脚 VBAT和ADD同时都掉电时才能让备份区复位。 volatile一个变量的存储单元可以在定义该变量的程序之外的某处被引用。 volatile主要是程序员要告诉编译器不要对其定义的这个变量进行优化,防止其不能被引用,不能被改变。 VDDA>2.4V ADC才能工作 VDDA>2.7V USB才能工作 VDD(1.8-3.6v) VBAT=1.8-3.6v VSS VSSA VREF必须接到地线 没有外部电源供电时必须VBAT接上VDD 使用PLL时,VDDA必须供电

printf("abs(x)=%d\n",x<0?(-1)*x:x) 条件编译是问号前边为真则取冒号前边的值,为假的,则取后边的值。 所以说上边这条打印的语句是打印x的绝对值。 //stm32f10x_nvic.c stm32f10x_lib.c stm32f10x_gpio.c stm32f10x_flash.c stm32f10x_rcc.c TIM6 TIM7基本定时器 (只有这两个定时器不能产生PWM) TIM1 TIM8高级控制定时器 TIM2 TIM3 TIM4 TIM5为通用定时器 其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出! 修改和自己写代码时候

STM32学习笔记

STM32学习笔记——时钟频率 ******************************** 本学习笔记基于STM32固件库V3.0 使用芯片型号:STM32F103 开发环境:MDK ******************************** 第一课时钟频率 STM32F103内部8M的内部震荡,经过倍频后最高可以达到72M。目前TI的M3系列芯片最高频率可以达到80M。 在stm32固件库3.0中对时钟频率的选择进行了大大的简化,原先的一大堆操作都在后台进行。系统给出的函数为SystemInit()。但在调用前还需要进行一些宏定义的设置,具体的设置在system_stm32f10x.c文件中。 文件开头就有一个这样的定义: //#define SYSCLK_FREQ_HSE HSE_Value //#define SYSCLK_FREQ_20MHz 20000000 //#define SYSCLK_FREQ_36MHz 36000000 //#define SYSCLK_FREQ_48MHz 48000000 //#define SYSCLK_FREQ_56MHz 56000000 #define SYSCLK_FREQ_72MHz 72000000 ST 官方推荐的外接晶振是8M,所以库函数的设置都是假定你的硬件已经接了8M 晶振来运算的.以上东西就是默认晶振8M 的时候,推荐的CPU 频率选择.在这里选择了: #define SYSCLK_FREQ_72MHz 72000000 也就是103系列能跑到的最大值72M 然后这个C文件继续往下看 #elif defined SYSCLK_FREQ_72MHz const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_SysClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_APB1Clk = (SYSCLK_FREQ_72MHz/2); const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz; 这就是在定义了CPU跑72M的时候,各个系统的速度了.他们分别是:硬件频率,系统时 钟,AHB总线频率,APB1总线频率,APB2总线频率.再往下看,看到这个了: #elif defined SYSCLK_FREQ_72MHz static void SetSysClockTo72(void); 这就是定义72M 的时候,设置时钟的函数.这个函数被SetSysClock ()函数调用,而SetSysClock ()函数则是被SystemInit()函数调用.最后SystemInit()函数,就是被你调用的了

STM32学习笔记(5)通用定时器PWM输出

STM32学习笔记(5):通用定时器PWM输出 2011年3月30日TIMER输出PWM 1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。 STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。 1.1PWM输出模式 STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下: 110:PWM模式1-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。 111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。 由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。 而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节,在此就不详细赘述了。 1.2PWM输出管脚 PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如

STM32学习笔记

1、GPIO函数: 输出: HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);//此例以PA12口为例 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); //此例以PA12口为例 HAL_GPIO_ TogglePin(GPIOA,GPIO_PIN_12); //此例以PA12口为例 2、串口函数: 1、串口发送/接收函数 HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制 HAL_UART_Receive();串口轮询模式接收,使用超时管理机制 HAL_UART_Transmit_IT();串口中断模式发送 HAL_UART_Receive_IT();串口中断模式接收 HAL_UART_Transmit_DMA();串口DMA模式发送 HAL_UART_Transmit_DMA();串口DMA模式接收 2、串口中断函数 HAL_UART_TxHalfCpltCallback();一半数据发送完成时调用 HAL_UART_TxCpltCallback();数据完全发送完成后调用 HAL_UART_RxHalfCpltCallback();一半数据接收完成时调用 HAL_UART_RxCpltCallback();数据完全接受完成后调用 HAL_UART_ErrorCallback();传输出现错误时调用 例程:串口接收中断 uint8_t aTxStartMessages[] = "\r\n******UART commucition using IT******\r\nPlease enter 10 characters:\r\n"; uint8_t aRxBuffer[20]; 2、在main函数中添加两个语句通过串口中断发送aTxStartMessage数组的数据和接收数据10个字符,保存在数组aRxBuffer中 HAL_UART_Transmit_IT(&huart1 ,(uint8_t*)aTxStartMessages,sizeof(aTxStartMessages)); //sizeof()可读取目标长度 HAL_UART_Receive_IT(&huart1,(uint8_t*)aRxBuffer,10); 3、在main.c文件后面添加中断接收完成函数,将接收到的数据又通过串口发送回去。 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { UNUSED(huart); HAL_UART_Transmit(&huart1,(uint8_t*)aRxBuffer,10,0xFFFF);//(uint8_t*)aRxBuffer为字符串地址,10为字符串长度,0xFFFF为超时时可以在中间加任何可执行代码。 }

STM32学习心得笔记

STM32学习心得笔记 时钟篇 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍, 但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外, 实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB 模块,其串行接口引擎需要一个频率为48MHz的时

钟源。该时钟源只能 从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL 必须使能, 并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL 输出、HSI或者HSE。系统时钟最 大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分 频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB 总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz), 另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

STM32学习笔记(18)-数据的保存和毁灭

数据的保存和毁灭(2) 和以前学到的有关数据保存不同,这里的数据保存还有“保密”之意,即一旦受到意外的侵入,STM32将毁灭数据。这是通过Tamper机制来实现的。 以下是数据手册中的有关说明: 5.3.1 侵入检测 当TAMPER引脚上的信号从0变成1或者从1变成0(取决于备份控制寄存器BKP_CR的TPAL 位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除。然而为了避免丢失侵入事件,侵入检测信号是边沿检测的信号与侵入检测允许位的逻辑与,从而在侵入检测引脚被允许前发生的侵入事件也可以被检测到。 ●当 TPAL=0 时:如果在启动侵入检测TAMPER引脚前(通过设置TPE位)该引脚已经为高电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现上升沿)。 ●当 TPAL=1 时:如果在启动侵入检测引脚TAMPER前(通过设置TPE位)该引脚已经为低电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现下降沿)。 设置BKP_CSR寄存器的TPIE位为’1’,当检测到侵入事件时就会产生一个中断。 在一个侵入事件被检测到并被清除后,侵入检测引脚TAMPER应该被禁止。然后,在再次写入备份数据寄存器前重新用TPE位启动侵入检测功能。这样,可以阻止软件在侵入检测引脚上仍然有侵入事件时对备份数据寄存器进行写操作。这相当于对侵入引脚TAMPER进行电平检测。 注:当V DD电源断开时,侵入检测功能仍然有效。为了避免不必要的复位数据备份寄存器,TAMPER引脚应该在片外连接到正确的电平。 显然,Tamper需要硬件与之配合。以上数据手册描述了硬件配置时的一些注意事项。 (1)可以是把引脚由低电平到高电平认为是一次侵入,也可以把引脚从高电平变到低电平认为是一次侵入,这通过TPAL来设置。

STM32自学笔记

一、原子位操作: 原子位操作定义在文件中。令人感到奇怪的是位操作函数是对普通的内存地址进行操作的。原子位操作在多数情况下是对一个字长的内存访问,因而位号该位于0-31之间(在64位机器上是0-63之间),但是对位号的范围没有限制。 原子操作中的位操作部分函数如下: void set_bit(int nr, void *addr)原子设置addr所指的第nr位 void clear_bit(int nr, void *addr)原子的清空所指对象的第nr位 void change_bit(nr, void *addr)原子的翻转addr所指的第nr位int test_bit(nr, void *addr)原子的返回addr位所指对象nr位int test_and_set_bit(nr, void *addr)原子设置addr所指对象的第nr位,并返回原先的值 int test_and_clear_bit(nr, void *addr)原子清空addr所指对象的第nr位,并返回原先的值 int test_and_change_bit(nr, void *addr)原子翻转addr所指对象的第nr位,并返回原先的值 unsigned long word = 0; set_bit(0, &word); /*第0位被设置*/ set_bit(1, &word); /*第1位被设置*/ clear_bit(1, &word); /*第1位被清空*/ change_bit(0, &word); /*翻转第0位*/ 二、STM32的GPIO锁定: 三、中断挂起: 因为某种原因,中断不能马上执行,所以“挂起”等待。比如有高、低级别的中断同时发生,就挂起低级别中断,等高级别中断程序执行完,在执行低级别中断。四、固文件: 固件(Firmware)就是写入EROM(可擦写只读存储器)或EEPROM(电可擦可编程只读存储器)中的程序。 五、固件库:包含各个外设或者内核的驱动头文件和C文件。 六、TIx的输入捕获滤波器(消抖): 采样频率fSAMPLING,采样次数N,如果以采样频率对一脉冲进行采样时,如果在N个采样方波里该脉宽不变,则视为一次有效的脉冲,否则视为无效的脉冲。 七、高级定时器的PWM互补输出: 常用于X相电机驱动,其中的互补输出则防止电机的死区出现。

STM32学习LCD的显示

STM32学习LCD的显示 1.LCD/LCM的基本概念 液晶显示器(Liquid Crystal Display: LCD)的构造是在两片平行的玻璃当中放置液态的晶体,两片玻璃中间有许多垂直和水平的细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面。 LCM(LCD Module)即LCD显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,PCB电路板,背光源,结构件等装配在一起的组件。 在平时的学习开发中,我们一般使用的是LCM,带有驱动IC和LCD屏幕等多个模块。 2.FSMC的基本概念 在STM32上开发LCD显示,可以有两种方式来对LCD进行操作,一种是通过普通的IO 口,连接LCM的相应引脚来进行操作,第2种是通过FSMC来进行操作。 可变静态存储控制器(Flexible Static Memory Controller: FSMC) 是STM32系列中内部集成256 KB以上FlaSh,后缀为xC、xD和xE的高存储密度微控制器特有的存储控制机制。之所以称为“可变”,是由于通过对特殊功能寄存器的设置,FSMC能够根据不同的外部存储器类型,发出相应的数据/地址/控制信号类型以匹配信号的速度,从而使得STM32系列微控制器不仅能够应用各种不同类型、不同速度的外部静态存储器,而且能够在不增加外部器件的情况下同时扩展多种不同类型的静态存储器,满足系统设计对存储容量、产品体积以及成本的综合要求。 FSMC有很多优点: 1.支持多种静态存储器类型。STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连。 2.支持丰富的存储操作方法。FSMC不仅支持多种数据宽度的异步读/写操作,而且支持对NOR、PSRAM、NAND存储器的同步突发访问方式。 3.支持同时扩展多种存储器。FSMC的映射地址空间中,不同的BANK是独立的,可用于扩展不同类型的存储器。当系统中扩展和使用多个外部存储器时,FSMC会通过总线悬空延迟时间参数的设置,防止各存储器对总线的访问冲突。 4.支持更为广泛的存储器型号。通过对FSMC的时间参数设置,扩大了系统中可用存储器的速度范围,为用户提供了灵活的存储芯片选择空间。 5.支持代码从FSMC扩展的外部存储器中直接运行,而不需要首先调入内部SRAM。FSMC包含两类控制器: 1.1个NOR闪存/SRAM控制器,可以与NOR闪存、SRAM和PSRAM存储器接口。 2.1个NAND闪存/PC卡控制器,可以与NAND闪存、PC卡,CF卡和CF+存储器接口。控制器产生所有驱动这些存储器的信号时序: 1.16位数据线,用于连接8位或16位的存储器; 2.26位地址线,最多可连续64MB的存储器(这里不包括片选线); 3.5位独立的片选信号线; 4.1组适合不同类型存储器的控制信号线: -控制读/写操作 -与存储器通信,提供就绪/繁忙信号和中断信号 -与所用配置的PC卡接口:PC存储卡、PC I/O卡和真正的IDE接口 从FSMC的角度看,可以把外部存储器划分为固定大小为256MB的4个存储块 · 存储块1用于访问最多4个NOR闪存或者PSRAM存储设备。这个存储区被划分为4个

STM32学习笔记:LCD的显示

年月日显示 . 地基本概念 液晶显示器( : )地构造是在两片平行地玻璃当中放置液态地晶体,两片玻璃中间有许多垂直和水平地细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面.文档来自于网络搜索 ( )即显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,电路板,背光源,结构件等装配在一起地组件.文档来自于网络搜索 在平时地学习开发中,我们一般使用地是,带有驱动和屏幕等多个模块. . 地基本概念 在上开发显示,可以有两种方式来对进行操作,一种是通过普通地口,连接地相应引脚来进行操作,第种是通过来进行操作.文档来自于网络搜索 可变静态存储控制器( : ) 是系列中内部集成以上,后缀为、和地高存储密度微控制器特有地存储控制机制.之所以称为“可变”,是由于通过对特殊功能寄存器地设置,能够根据不同地外部存储器类型,发出相应地数据地址控制信号类型以匹配信号地速度,从而使得系列微控制器不仅能够应用各种不同类型、不同速度地外部静态存储器,而且能够在不增加外部器件地情况下同时扩展多种不同类型地静态存储器,满足系统设计对存储容量、产品体积以及成本地综合要求.文档来自于网络搜索 有很多优点: . 支持多种静态存储器类型.通过可以与、、、和存储器地引脚直接相连.文档来自于网络搜索 . 支持丰富地存储操作方法.不仅支持多种数据宽度地异步读写操作,而且支持对、、存储器地同步突发访问方式.文档来自于网络搜索 . 支持同时扩展多种存储器.地映射地址空间中,不同地是独立地,可用于扩展不同类型地存储器.当系统中扩展和使用多个外部存储器时,会通过总线悬空延迟时间参数地设置,防止各存储器对总线地访问冲突.文档来自于网络搜索 . 支持更为广泛地存储器型号.通过对地时间参数设置,扩大了系统中可用存储器地速度范围,为用户提供了灵活地存储芯片选择空间.文档来自于网络搜索 . 支持代码从扩展地外部存储器中直接运行,而不需要首先调入内部. 包含两类控制器: . 个闪存控制器,可以与闪存、和存储器接口. . 个闪存卡控制器,可以与闪存、卡,卡和存储器接口. 控制器产生所有驱动这些存储器地信号时序: . 位数据线,用于连接位或位地存储器; . 位地址线,最多可连续地存储器(这里不包括片选线); . 位独立地片选信号线; . 组适合不同类型存储器地控制信号线: 控制读写操作 与存储器通信,提供就绪繁忙信号和中断信号 与所用配置地卡接口:存储卡、卡和真正地接口 从地角度看,可以把外部存储器划分为固定大小为地个存储块 ·存储块用于访问最多个闪存或者存储设备.这个存储区被划分为个区,并有个专用地片选.文档来自于网络搜索·存储块和用于访问闪存设备,每个存储块连接一个闪存. ·存储块用于访问卡设备 每一个存储块上地存储器类型是由用户在配置寄存器中定义地. 注意:只是提供了一个控制器,并不提供相应地存储设备,至于外设接地是什么设备,完全是由用户自己选择,只要能用于控制,就可以,像本次实验中,我们接地就是.文档来自于网络搜索 . 本例中地使用 由于本例只是利用对进行操作,因此不用完全懂得地所有功能,而是懂得一部分相应地操作即可.文档来自于网络搜索 . 包括哪几个部分

STM32学习笔记-USART程序解释(原子)

USART程序分析 一 .H文件 #ifndef __USART_H #define __USART_H #include #include "stdio.h" extern u8 USART_RX_BUF[64]; //接收缓冲,最大63个字节.末字节为换行符extern u8 USART_RX_STA; //接收状态标记 //如果想串口中断接收,请不要注释以下宏定义 //#define EN_USART1_RX 使能串口1接收 void uart_init(u32 pclk2,u32 bound); #endif 解释:extern 作用域:如果整个工程由多个文件组成,在一个文件中想引用另外一个文件中已经定义的外部变量时,则只需在引用变量的文件中用extern关键字加以声明即可。可见,其作用域从一个文件扩展到多个文件了。 例子: 文件a.c的内容: #include int BASE=2; //变量定义 int exe(int x); //外部函数提前声明 int main(int argc, char *agrv[]) { int a=10; printf("%d^%d = %d\n",BASE,a,exe(a)); return 0; } 文件b.c的内容: #include extern BASE; //外部变量声明 int exe(int x) { int i; int ret=1; for(i=0;i

STM32学习笔记(初学者快速入门

STM32学习笔记(初学者快速入门 STM32 学习笔记 从51 开始单片机玩了很长时间了有51PICAVR 等等早就想跟潮 流玩玩ARM 但一直没有开始原因-----不知道玩了ARM 可以做什么对我自 己而言如果为学习而学习肯定学不好然后cortex-m3 出来了据说这 东西可以替代单片机于是马上开始关注也在第一时间开始学习可惜一开始 就有点站错了队选错了型仍是对我自己而言我希望这种芯片应该是满大 街都是随便哪里都可以买得到但我选的第一种显然做不到为此大概浪费

了一年多时间吧现在回到对我来说是正确的道路上来啦边学边写点东西 这里写的是我的学习的过程显然很多时候会是不全面的不系统的感 悟式的甚至有时会是错误的有些做法会是不专业的那么为什么我还要写 呢这是一个有趣的问题它甚至涉及到博客为什么要存在的问题显然博客 里面的写的东西其正确性权威性大多没法和书比可为什么博客会存在呢 理由很多我非专家只说我的感慨 我们读武侠小说总会有一些创出独门功夫的宗师功夫极高然后他的弟 子则基本上无法超越他我在想这位宗师在创造他自己的独门功

夫时必然会 有很多的次的曲折弯路甚至失败会浪费他的很多时间而他教给弟子时 则已去掉了这些曲折和弯路当然更不会把失败教给弟子按理说效率应该更 高可是没用弟子大都不如师为什么呢也许知识本身并不是最重要的获 取知识的过程才是最重要的也许所谓的知识并不仅仅是一条条的结论而是 附带着很多说不清道不明的东西如植物的根一条主根上必带有大量的小小的 触须 闲话多了些就权当前言了下面准备开始 一条件的准备

我的习惯第一步是先搭建一个学习的平台原来学51PICAVR 时都 是想方设法自己做些工具实验板之类现在人懒了直接购买成品了 硬件电路板火牛板 软件有keil 和iar 可供选择网上的口水仗不少我选keil理由很简单 这个我熟目前要学的知识中软硬件我都不熟所以找一个我有点熟的东西 就很重要在我相当熟练之前肯定不会用到IAR如果真的有一天不得不用I AR 相信学起来也很容易因为这个时候硬件部分我肯定很熟了再加上有ke il 的基础所以应该很容易学会了

STM32学习笔记(关于时钟)

STM32学习----时钟(转载) 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 HSE/LSE时钟源 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz 的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

STM32学习笔记

FLASH篇: 一、闪存:主存储器,信息块和闪存存储器接口寄存器等3部分组成。 1、主存储器:存放代码与数据常量(编译器编译完成后CODE=,RO=,RW=,ZI=,依次为代码,常量,初始化变量,未初始化变量),即前面两个。B0,B1都为GND时,从0x08000000开始运行代码。 2、信息块:分为启动代码和用户选择字节。启动代码是生产线上少些进去的,用于USART1串口下载时使用,B0=1,B1=0时运行这段代码。用户选择字用于配制写保护杜保护等功能。 3、闪存存储器接口寄存器:控制闪存的读写,用于控制整个模块。 二、闪存编程/擦除控制器(FPEC) 对主存储器和信息块的写入管理。在执行写操作时,任何对闪存读操作都会锁住总线,在写操作完成后读操作才正确而执行。 包含有7个32位寄存器: 键寄存器FLASH_KEYR; 选择字节键寄存器FLASH_OPTKEYR; 闪存控制寄存器FLASH_CR; 闪存地址寄存器FLASH_AR; 闪存状态寄存器FLASH_SR; 选择字节寄存器FLASH_ORR; 写保护寄存器FLASH_WRPR; 复位后,FPEC模块是被保护的,不能写入FLASH_CR寄存器,通过写入特定的序列到FLASH_KEYR寄存器可以打开FPEC模块(写入KEY1和KEY2),当其中有一个写入错误,写入RDPRT进行解锁。 RDPRT=0X0000000A5; KEY1=0X45670123; KEY2=0XCDEF99AB; 注:每次必须写入16位,也只有写16位。 三、闪存读取 直接寻址方式,任何32为数据读操作都能访问闪存模块的内容并得到相应的数据。读操作时FLASH_ACR寄存器配置FLASH等待周期为2。 DATA=*(U16)*ADDR; 四、闪存的编程和擦除

牛人的STM32学习笔记(寄存器版本)

一、GPIO口的配置 STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个 双向IO组成。并且没个IO口均可配置成8种模式(4种输入模式,4种输出模式)。不管 配置哪个IO口也不论将其配置成哪种模式(但是配置成哪种模式要看具体应用,参考《中 文参考手册》第105页)都可以按以下步骤来进行配置: (1)使能PORTx(x=A~G)时钟 这里就得操作寄存器RCC_APB2ENR(32为寄存器)了 15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN 7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN RCC_APB2ENR的0~15位(06~32位保留) 第2~8分别是使能GPIOA~GPIOG时钟的,只要将其置“1”即可,如 RCC_APB2ENR|=1<<2;就是使能GPIOA的时钟;其余IO口的始终使能一次类推。 (2)对相应的IO模式进行配置,低8位配置GPIOx_CRL;高8位配置GPIOx_CRH 31 30 29 28 27 26 25 24 CNF7[1:0] MODE7[1:0] CNF6[1:0] MODE6[1:0] 23 22 21 20 19 18 17 16 CNF5[1:0] MODE5[1:0] CNF4[1:0] MODE4[1:0] 15 14 13 12 11 10 9 8 CNF3[1:0] MODE3[1:0] CNF2[1:0] MODE2[1:0] 7 6 5 4 3 2 1 0 CNF1[1:0] MODE1[1:0] CNF0[1:0] MODE0[1:0] GPIOx_CRL(x=A~G(端口配置低寄存器x=A…E) 该寄存器用于配置GPIOx的低8位,具体8种模式的配置见《中文参考手册》例如: GPIOD->CRL&=0XFFFFF0FF;GPIOD->CRL|=0X00000300;/PD.2推挽输出;其余IO口的 低8位以此类推。 31 30 29 28 27 26 25 24 CNF15[1:0] MODE15[1:0] CNF14[1:0] MODE14[1:0] 23 22 21 20 19 18 17 16 CNF13[1:0] MODE13[1:0] CNF12[1:0] MODE12[1:0] 15 14 13 12 11 10 9 8 CNF11[1:0] MODE11[1:0] CNF10[1:0] MODE10[1:0] 7 6 5 4 3 2 1 0 CNF9[1:0] MODE9[1:0] CNF8[1:0] MODE8[1:0] GPIOx_CRH(端口配置高寄存器x=A…E) 该寄存器用于配置GPIOx的高8位,具体8种模式的配置见《中文参考手册》例如: GPIOA->CRH&=0XFFFFFFF0;;GPIOA->CRH|=0X00000003;//PA8 推挽输出;其余IO口 的高8位以此类推。

STM32学习笔记系统时钟和SysTick定时器

STM32学习笔记(3):系统时钟和SysTick定时器 1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL 的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但 是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。 STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为 48MHz的时钟源。该时钟源只能从PLL端获取,可以选择为1.5分频或者1分频,也就是,当需使用到USB模块时,PLL必须使能,并且时钟配置为48MHz 或72MHz。 另外STM32还可以选择一个时钟信号输出到MCO脚(PA.8)上,可以选择为PLL输出的2分频、HSI、HSE或者系统时钟。 系统时钟SYSCLK,它是提供STM32中绝大部分部件工作的时钟源。系统时钟可以选择为PLL输出、HSI、HSE。系系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各个模块使用,AHB分频器可以选择1、2、4、8、16、64、128、256、512分频,其分频器输出的时钟送给5大模块使用: (1)送给AHB总线、内核、内存和DMA使用的HCLK时钟; (2)通过8分频后送给Cortex的系统定时器时钟; (3)直接送给Cortex的空闲运行时钟FCLK; (4)送给APB1分频器。APB1分频器可以选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一

相关主题
文本预览
相关文档 最新文档