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

合集下载

STM32自学笔记

STM32自学笔记

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位inttest_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(电可擦可编程只读存储器)中的程序。

STM32学习笔记2

STM32学习笔记2

1.通信:设备间信息的交互有线:以太网,USART,USB,CAN,485等无线:wifi,蓝牙,zigbee,射频,红外,2.4G,2G、3G、4G、5G,NB_IOT,广播等2.通信方式划分并行通信:一次传输多位数据,传输速度快,MCU与内存间串行通信:一次传输一位数据串行通信按照数据传输是否同步分为:同步通信:数据传送是以数据块(一组字符)为单位,字符与字符之间、字符内部的位与位之间都同步,需要有同步时钟。

异步通信:字符与字符间的传送是完全异步的,位与位之间的传送基本上是同步的。

串行通信按照数据传输方向划分:单工:数据单向传输-- 广播,收音机等半双工:数据可以双向传输,同一时刻,只能发送或者接收-- 对讲机,485等全双工:数据双向传输-- 手机,SPI等3.串行通信1.物理层1.引脚TXD 数据发送管脚RXD 数据接收管脚GND 信号地2.连接方式a.直接相连-- 模块与模块间,设备与模块间b.RS232 负逻辑电平 1 -- -3~-15V 0 -- +3~+15V-- 设备与设备间,设备与模块间B转串口-- 设备与设备间2.数据链路层(协议)-- 位协议RS232协议:起始位数据位奇偶检验位停止位位数: 1 8/9 1 1~2电平:0 1/0 1/0 1奇偶检验:数据位1的个数+校验位中1的个数奇校验:数据位1的个数+校验位中1的个数为奇数个。

发送的数据:0110 1001发送数据:0110 1001 1接收数据:0110 0001 1 -- 错误0111 0001 1 -- 正确(错误)位:clk周期常用的格式:1+8+0+13.波特率数据传输的速率,每秒传输多少位数据。

常用的波特率:9600,115200,38400等4.STM32中串口的介绍1.数量-- 3个2.特性全双工异步通信小数波特率发生器系统数据字长度可编程(8 位或9 位)停止位可配置- 支持 1 或 2 个停止位发送器和接收器具有单独使能位传输检测标志:—接收缓冲区已满—发送缓冲区为空—传输结束标志3.结构框图1.数据发送和接收数据接收:data = USARTx->DR;数据发送:USARTx->DR = data;2.发送接收控制 -- CR1,CR2,CR33.发送和接收什么时候完成 -- SRTXE:数据发送完成,TDR无数据,移位寄存器有数据TC:数据发送完成,TDR无数据,移位寄存器无数据RXNE:0 –未接收数据 1 - 接收到数据4.波特率5.软件编程1.查看原理图PA9、PA10 复用功能6.蓝牙CC2541工作模式:1.命令响应模式-- 使用AT指令集2.透传模式(透明传输)-- 使用串口发送消息PA6 –通用推挽输出中断配置:优先级4位:占先优先级+ 次级优先级(数字越小,优先级越高)占先优先级:中断发生时能否被打断,谁先执行次级优先级:占先优先级相同时,中断同时到来,优先级高的先执行作业:APP 发送数据*12# ,电机转动发送数据*34# ,电机停止转动。

stm32自学笔记共20页

stm32自学笔记共20页


LED0=1;

LED1=0;

delay_ms(300);

}
•}
第二章 跑马灯实验
• Led.c函数
• void LED_Init(void)
•{

RCC->APB2ENR|=1<<2; //使能PORTA时钟

GPIOA->CRH|=0XFFFFFFFF3;//PA8 推挽输出

GPIOA->ODR|=1<<8; //PA8 输出高
• JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD,在原理图上可以看 到PA13和PA15为键盘和JTAG与SWD所共用,而这两种方针接口,他们 和普通的IO口公用,当想使用普通IO口时,必须先把他们关闭。在这 个函数里面设置参数,如果为二进制数00,则代表全部使能,如果是 二进制数01,则是能SWD,如果是10,则表示全部关闭。JTAG是一种 国际标准测试协议,主要用于芯片内部的测试。
• }要想实现一个点亮led小灯的功能,最少只需对3个寄存器进行设 置,第一步是设置外设时钟使能先把PORTA时钟使能,接下来把IO
口设置为输出,在接下来设置输出为高电平还是低电平,这里使用 推挽输出(3.3v),推挽输出主要是增强驱动能力,为外部提供大电 流。
第二章 跑马灯实验
• #ifndef __LED_H • #define __LED_H • #include "sys.h" • #define LED0 PAout(8)// PA8 • #define LED1 PDout(2)// PD2 • void LED_Init(void);//初始化

STM32学习笔记

STM32学习笔记

串口:一. USART_ITConfig(USART1, USART_IT_TXE, ENABLE):只要发送寄存器为空,就会一直有中断,因此,要是不发送数据时,把发送中断关闭,只在开始发送时,才打开。

二.以下是字符发送的配置过程,注意第6点,在设置USART_CR1中的TE位时,会发送一个空闲帧作为第一次数据发送,所以即便你执行了USART_ClearFlag(USART1, USART_FLAG_TC); (这个函数肯定在空闲帧数据发送完成前执行),所以当空闲帧发送完后,就进入发送完成中断。

配置步骤:1. 通过在USART_CR1寄存器上置位UE位来激活USART2. 编程USART_CR1的M位来定义字长。

3. 在USART_CR2中编程停止位的位数。

4. 如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMA T)。

按多缓冲器通信中的描述配置DMA寄存器。

5. 利用USART_BRR寄存器选择要求的波特率。

6. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。

7. 把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。

在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。

8. 在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的传输结束。

当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

解决的办法:方法一在执行USART_ITConfig(USART1, USART_IT_TC, ENABLE); 之前,先延时一段时间,基本上比一个字符发送的时间长一点就可以了,然后再执行USART_ClearFlag(USART1, USART_FLAG_TC);方法二:在执行USART_ITConfig(USART1, USART_IT_TC, ENABLE); 之前,USART_ClearFlag(USART1, USART_FLAG_TC);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){; //等待空闲帧发送完成后再清零发送标志}USART_ClearFlag(USART1,USART_FLAG_TC);三.TXE:发送缓冲器空闲标志RXNE:接收缓冲区非空IAP:一.问:这几天在折腾STM32的IAP,参考了两个例程,一个AN2557,然后一个就是标准外设库内的flash例程总结IAP:1.Flash解锁 FLASH_Unlock();2.清除Flash所有的未完成的标志位 FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);3.根据文件大小擦除Flashfor(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE ); EraseCounter++){FLASHStatus = FLASH_ErasePage(StartAddr + (FLASH_PAGE_SIZE * EraseCounter));}4.编程Flashwhile((Address < EndAddr) && (FLASHStatus == FLASH_COMPLETE)){FLASHStatus = FLASH_ProgramWord(Address, Data);Address = Address + 4;}5.检验编入数据的正确性while((Address < EndAddr) && (MemoryProgramStatus != FAILED)){if((*(__IO uint32_t*) Address) != Data){MemoryProgramStatus = FAILED;}Address += 4;}在以上几步中,如果上面没有问题的话,提出下面几个疑问1.假如我的应用程序的地址应该从0x8003000开始,那么我把后面的页全部擦除是否可以? 虽然我的程序可能只占到0x8003000-0x8005000 那么这之后的页是否也可以一并擦除?2.在编程的时候有个很小的问题,因我的数据都是以字节(byte)的形式储存的,在写的时候因为只能以半字(16位)或一个字(32位)的方式编程,那么如果我的bin文件的最后一个字节并不够两个字节,怎么办?举例:我的bin文件的大小是501个字节(8位),我的写入方法是这样的:data[501] = {X,X,X...}//应用程序bin文件内容temp = data[0];temp = temp << 8;temp |= data[1];temp = temp << 8;temp |= data[2];teme = temp << 8;teme |= data[3];//待写入得数据FLASHStatus = FLASH_ProgramWord(Address, temp);//写入flash如果像这样的话,那么不能被4整除的那一个字节怎么办?3.IAP程序中有一处一直很迷惑,不能理解/* Test if user code is programmed starting from address "ApplicationAddress" */if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000){ /* Jump to user application */JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);Jump_To_Application = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();}程序的整体是要跳出IAP引导区跳到应用程序区.那么这句判断的依据是什么?if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)倘若我今天的程序是重0x8003000处开始,那么明天我升级一个程序,他的开始是0x80080000呢?这里需要改吗?0x2FFE0000 0x20000000 这两个数我在AN2557的例子代码里反复寻找,并没有哪里出现,那么又是怎么跟用户的应用程序关联的呢?还有如果将上面的例子直接这样更改,是否可以达到跳转到应用程序区的目的呢?/* Jump to user application */JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); //这里为何要+4 ?+了4不就跳过出应用程序的入口了吗?Jump_To_Application = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();4.关于Flash的写保护问题,在3.0标准外设库中Flash还有另外一个例子,就是关于保护的无疑flash的保护是对程序的一个安全保障,但目前我买的新片子(未进行过任何保护方面的操作)中,是否不需要考虑这些问题,直接擦除,然后编程即可?5.有什么理由要“今天的程序是重0x8003000处开始,明天又升级一个程序,他的开始是呢”?第1没有必要,第2是自寻烦恼。

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

STM32学习笔记(初学者快速入门)a
#include "stm32f10x_conf.h" #endif 看来,是这个 USE_STDPERIPH_DRIVER 没有被定义啊,于是,人为地去掉 条件: //#ifdef USE_STDPERIPH_DRIVER
#include "stm32f10x_conf.h" //#endif 再次编译,果然就 OK 了。可是,可是,也不能就这么去掉啊,怎么办呢?万能 的网啊,一搜果然就有了。
说说我怎么学的吧。 找个例子,如 GPIO,可以看到其结构如下: SOURCE(文件夹)
- APP(文件夹) -CMSIS(文件夹) -STM32F10x_StdPeriph_Driver(文件夹) Lis(文件夹) OBJ(文件夹) 其中 SOURCE 中保存的是应用程序,其中又有好多子文件夹,而 CMSIS 文件 夹中和 STM32F10x_StdPeriph_Driver 文件夹中是 ST 提供的库,这样,如果要 做新的工程只要将这个文件夹整个复制过来就行,其中 APP 中保存自己的代码。 因为我们用 51 单片机时一般比较简单,有时就一个文件,所以通常不设置专 门的输出文件夹,而这里做开发,通常会有很多个文件加入一个工程中,编译过 程中会产生很多中间文件,因此设置专门的文件夹 LIS 和 OBJ 用来保存中间文 件。 下面就将设置简单描述一下。 将复到过来的 GPIO 根目录下的所有文件删除,因为我们要学着自己建立工程。
到设置 C/C++页面 在那个 define 中加入“USE_STDPERIPH_DRIVER,STM32F10X_HD” 当然,去掉条件编译前面的注释,回到原样。 再次编译,一切顺利。可是,原来的工程例子也没有加这个啊,怎么回事呢?再 次打开原来的例子,找到 stm32f10x.h,可以看到有这么一行:

STM32学习笔记

STM32学习笔记

一、GPIO操作IO 的方法:1)使能IO 口时钟。

调用函数为RCC_APB2PeriphClockCmd()。

2)初始化IO 参数。

调用函数GPIO_Init();3)操作IO。

GPIO_Mode有:GPIO_Mode_AIN = 0x0, //模拟输入GPIO_Mode_IN_FLOATING = 0x04, //浮空输入GPIO_Mode_IPD = 0x28, //下拉输入GPIO_Mode_IPU = 0x48, //上拉输入GPIO_Mode_Out_OD = 0x14, //开漏输出GPIO_Mode_Out_PP = 0x10, //通用推挽输出GPIO_Mode_AF_OD = 0x1C, //复用开漏输出GPIO_Mode_AF_PP = 0x18 //复用推挽IO 口速度设置:GPIO_Speed_10MHz = 1,GPIO_Speed_2MHz,GPIO_Speed_50MHz初始化结构体初始化GPIO 的常用格式://初始化PGIO_PC.4为上拉输入GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //PC.4 端口配置GPIO_Mode_IPU = 0x48, //上拉输入GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能,GPIOA 时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.0 发送端读GPIOA.5 的电平状态:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);控制IO 口的输出状态:void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);设置GPIOA 的第1 个端口值为1,那么你只需要往寄存器BSRR 的低16 位对应位写1 即可:GPIOA->BSRR=1<<1;如果你要设置GPIOA 的第1 个端口值为0,你只需要往寄存器高16 位对应为写1 即可:GPIOA->BSRR=1<<(16+1)对应函数void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);STM32 的IO 口做输入使用的时候,是通过调用函数GPIO_ReadInputDataBit()来读取IO 口的状态的在配置STM32 外设的时候,任何时候都要先使能该外设的时钟!二、串口串口设置的一般步骤可以总结为如下几个步骤:1) 串口时钟使能,GPIO 时钟使能2) 串口复位3) GPIO 端口模式设置4) 串口参数初始化5) 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)6) 使能串口7) 编写中断处理函数1.串口时钟使能。

STM32入门教程

STM32入门教程

STM32入门教程STM32是一款由意法半导体(STMicroelectronics)开发的32位微控制器系列。

它是一种广泛应用于嵌入式系统设计的芯片,具有高性能、低功耗、丰富的外设接口以及可编程的特点。

对于初学者来说,入门STM32可能会有一定的难度。

本篇教程将逐步介绍STM32的基本知识和入门方法,帮助初学者快速上手。

第一部分:STM32简介在入门STM32之前,我们首先了解一些基本的背景知识。

STM32系列采用了ARM Cortex-M内核,具有不同的系列和型号,例如STM32F1xx、STM32F4xx等。

不同的系列和型号拥有不同的性能和外设接口,所以在选型时需要根据具体需求进行选择。

第二部分:开发环境搭建第三部分:编写第一个程序第四部分:外设的使用STM32拥有丰富的外设接口,包括GPIO、UART、SPI、I2C等。

在这一部分,我们将详细介绍如何使用这些外设。

以GPIO为例,我们将学习如何配置GPIO引脚的输入输出模式,如何控制GPIO引脚的高低电平,以及如何使用外部中断功能。

类似地,我们还将介绍UART、SPI和I2C等外设的使用方法。

第五部分:中断的处理中断是STM32中一个非常重要的特性。

它可以让我们在程序运行的同时,对外部事件做出及时的响应。

本节我们将学习如何配置和使用中断。

首先,我们需要了解中断向量表和中断优先级的概念。

然后,学习如何编写中断处理函数,并配置和启用中断。

最后,通过一个例子,演示如何使用中断来处理外部事件,例如按键的按下和释放。

第六部分:时钟和定时器时钟和定时器是嵌入式系统中非常重要的功能模块。

STM32提供了多个时钟源和定时器模块,可以用于各种定时任务和时序要求。

在这一部分,我们将学习如何配置时钟源和时钟分频器,以及如何配置和使用定时器。

通过一个实例,我们将学习如何使用定时器来产生精确的延时和周期性的中断信号。

第七部分:存储器和编程方法STM32拥有多种存储器类型,包括闪存、RAM和EEPROM等。

手把手教你STM32笔记

手把手教你STM32笔记

手把手教你STM32笔记stm32f1031、io口处理io口包含7个寄存器配置寄存器两个:crl(32),crh(32)数据寄存器两个:idr(32),odr(32),但是他们就用了16边线位登位寄存器:bsrr(32)登位寄存器:brr(16)锁存寄存器:lckr(32)常用的有前面四个:其中前面两个是用来设置的,后面两个是用来操作的。

每个io 口占用四位进行设置(低两位是mode,高两位是cnf),每组16个,总共需要64个位设置,分别从crl低位开始,到crh的高位结束。

每个io口四位二进制的常用布局:演示输出模式(adc):0x0;推挽输出模式(输出口50mhz):0x3;上/下拉输入模式(输入口用):0x8;复用输出(第二供能):0xb;stm32f407自学笔记1、系统时钟的设置:stm32_clock_init(168,4,2,7);参数分别就是:plln,pllm,pllp,pllqhse分频pllm之后为vco的输入,一般vco的输入要求为1~2mhz,一般建议取为2mhz,防止pll抖动。

vco输出是输入的plln倍频,sysclk在去pll输出时,sysclk=pll=hse/pllm*plln/pllp而pllq是为48mhz时钟配置用的,clk48=hse/pllm*plln/pllq所以要设置系统时钟为168mhz时候推荐的参数取值为sysclk=pll=hse/pllm*plln/pllp=8/4*168/2=168mhzclk48=hse/pllm*plln/pllq=8/4*168 /7=48mhz2、延时函数设置:delay_init(168);延时函数参数为系统时钟sysclk初始化后就可以调用延时函数:delay_ms(ms);参数不能大于65536,因为参数是16位数delay_us(us);参数不能大于7989153、普通io的使用a.首先是使能时钟rcc->ahb1enr|=1<<5;在该寄存器适当的边线1即可b.io口模式设置:gpio_set(gpiof,pin9|pin10,gpio_mode_out,gpio_otype_pp,gpio_speed_100m,gpio_pup d_pu);参数分别就是:gpiox,pin9|pin10(具体对应的口,可以使用与的关系)因为每种占一位#definepin0#definepin1#definepin2#definepin3#definepin4#definepin5#definepin6#definepin7#definepin8#definepin9#definepin10#definepin11#definepin12#definepin 13#definepin14#definepin151<<01<<11<<21<<31<<41<<51<<61<<71<<81<<91<<101<<111<<121<<131<<141<<15mode:四种,各个模式只能设置一种#definegpio_mode_in0#definegpio_mode_out//普通输出模式1//普通输出模式#definegpio_mode_af#definegpio_mode_ain输入推挽或者开漏挑选:#definegpio_otype_pp#definegpio_otype_od23//af功能模式//演示输出模式01//推挽输入//开漏输入推挽输出可输出强的高、低电平,用于连接数字器件开漏输入相等于三极管的集电极,电流型驱动,只可以输入弱的低电平,高电平需外扎。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我们读武侠小说,总会有一些创出独门功夫的宗师,功夫极高,然后他的弟 子则基本上无法超越他。我在想,这位宗师在创造他自己的独门功夫时,必然会 有很多的次的曲折、弯路、甚至失败,会浪费他的很多时间,而他教给弟子时, 则已去掉了这些曲折和弯路,当然更不会把失败教给弟子,按理说,效率应该更 高,可是没用,弟子大都不如师。为什么呢?也许知识本身并不是最重要的,获 取知识的过程才是最重要的?也许所谓的知识,并不仅仅是一条条的结论,而是 附带着很多说不清道不明的东西?如植物的根,一条主根上必带有大量的小小的 触须? 闲话多了些,就权当前言了。下面准备开始。 一、条件的准备
STM32 学习笔记
从 51 开始,单片机玩了很长时间了,有 51,PIC,AVR 等等,早就想跟潮 流玩玩 ARM,但一直没有开始,原因-----不知道玩了 ARM 可以做什么(对我自 己而言)。如果为学习而学习,肯定学不好。然后 cortex-m3 出来了,据说,这 东西可以替代单片机,于是马上开始关注。也在第一时间开始学习,可惜一开始 就有点站错了队,选错了型(仍是对我自己而言)。我希望这种芯片应该是满大 街都是,随便哪里都可以买得到,但我选的第一种显然做不到。为此,大概浪费 了一年多时间吧,现在,回到对我来说是正确的道路上来啦,边学边写点东西。
第一次进入时 Include Paths 文本框中是空白的,点击其后的按钮打开对话框, 增加相应的路径
这样路径就设好了。单击 OK,回到上一界面,然后再单击 OK,退出设置,即 可编译、链接。 下一会要试一试新的 3.12 版的库效果如何了。
STM32 学习笔记(3)
升级库 光盘中所带的例子是 3.10 的,另外还有一个 3.12 的,我 试着将 3.12 的库替代 原来的库,还真有问题,下面就简述问题及解决方法。 (1)将库文件解压 库文件名是:stm32f10x_stdperiph_lib.zip,解压后放在任意一个文件夹中。 (2)由于原作者做了很好的规划,每一个项目中都分成三个文件夹,并且在 s ource 文件夹中又做了 3 个文件夹,其中 APP 文件夹是放自己写的文件的,其 他的两个是从库中复制过来的,因此,想当然地把 3.1.2 版本中相同的两个文件 夹: CMSIS 和 STM32F10x_StdPeriph_Driver 直接复制过来,以为一切 OK,结果 一编译,出来一堆错误。 其中有错误:
这里写的是我的学习的过程,显然,很多时候会是不全面的,不系统的,感 悟式的,甚至有时会是错误的,有些做法会是不专业的。那么,为什么我还要写 呢?这是一个有趣的问题,它甚至涉及到博客为什么要存在的问题。显然,博客 里面的写的东西,其正确性、权威性大多没法和书比,可为什么博客会存在呢? 理由很多,我非专家,只说我的感慨。
STM32 学习笔记(2)
本想着偷点懒的,没想到竞被加了“精”,没办法啦,只能勤快点啦。。。 硬件调通后,就要开始编程了。 编程的方法有两种,一种是用 st 提供的库,另一种是从最底层开始编程,网上 关于使用哪种方法编程的讨论很多,据说用库的效率要低一些。但是用库编程非 常方便,所以我还是从库开始啦。库是 ST 提供的,怎么说也不会差到哪里,再 说了,用 32 位 ARM 的话,开发的观念也要随之改变一点了。
Source\App\main.c(7): error: #20: identifier "GPIO_InitTypeDef" is undefin ed .... 还有大量的警告:
Source\STM32F10x_StdPeriph_Driver\src\stm32f10x_flash.c(130): warnin g: #223-D: function "assert_param" declared implicitly 看了看,在 APP 文件夹中还有一些不属于自己的东西: stm32f10x_conf.h,stm32f10x_it.h,stm32f10x_it.c,打开一看,果然是 3.10 版本的,没说的,换。。。。,找到 STM32F10x_StdPeriph_Lib_V3.1.2\Proje
我的习惯,第一步是先搭建一个学习的平台。原来学 51,PIC,AVR 时,都 是想方设法自己做些工具,实验板之类,现在人懒了,直接购买成品了。
硬件电路板:火牛板 软件:有 keil 和 iar 可供选择。网上的口水仗不少,我选 keil,理由很简单, 这个我熟。目前要学的知识中,软、硬件我都不熟,所以找一个我有点熟的东西 就很重要。在我相当熟练之前,肯定不会用到 IAR,如果真的有一天不得不用 I AR,相信学起来也很容易,因为这个时候硬件部分我肯定很熟了,再加上有 ke il 的基础,所以应该很容易学会了。 调试工具:JLINK V8。这个不多说了,价格便宜又好用,就是它了。 二、热身 网上选购的,付了款就是等了。拿到包裹,端详良久,起身。。。。沐浴, 更衣,焚香,,, , , 总得先吃晚饭,洗澡,再点个电蚊香什么的吧。
接下来设定目标输出文件夹。上面这个图怎么出来的就不说啦,单击“Select Fo ler for Objects...”,在弹出来的对话框中选择 OBJ 文件夹。
同样方法,选择 List 文件的输出文件夹。 设置好后,如果直接编译是不行的,会出错。还需要提供头文件所在位置。单击 c/C++标签页.
ห้องสมุดไป่ตู้
,拆包 细细端详,做工精良,尤其那上面的 3.2 吋屏,越看越喜欢。接下来就是一阵折 腾了,装 JLINK 软件,给板子通电,先试试 JLINK 能不能与电脑和板子通信上 了。真顺,一点问题也没有。于是准备将附带的程序一个一个地写进去试一试。 一检查,大部分例子的 HEX 文件并没有给出,这要下一步自己生成,但是几个 大工程的例子都有 HEX 文件,如 MP3,如 UCCGI 测试等,写完以后观察程序 运行的效果。因为之前也做过彩屏的东西,知道那玩艺代码量很大,要流畅地显 示并不容,当时是用 AVR 做的,在 1.8 吋屏上显示一幅画要有一段时间。现在 看起来,用 STM32 做的驱动显示出来的画面还是很快的,不过这里显示的大部 分是自画图,并没有完整地显示一整幅的照片,所以到底快到什么程度还不好说, 看来不久以后这可以作为一个学习点的。 一个晚上过去了,下一篇就是要开始 keil 软件的学习了。
中的 bin 映像(image)文件,这一点清注意区别。 一个 ARM 程序包含 3 部分:RO,RW 和 ZI RO 是程序中的指令和常量 RW 是程序中的已初始化变量 ZI 是程序中的未初始化的变量 由以上 3 点说明可以理解为: RO 就是 readonly, RW 就是 read/write, ZI 就是 zero ARM 映像文件的组成 所谓 ARM 映像文件就是指烧录到 ROM 中的 bin 文件,也称为 image 文件。以 下用 Image 文件来称呼它。 Image 文件包含了 RO 和 RW 数据。 之所以 Image 文件不包含 ZI 数据,是因为 ZI 数据都是 0,没必要包含,只要程 序运行之前将 ZI 数据所在的区域一律清零即可。包含进去反而浪费存储空间。 Q:为什么 Image 中必须包含 RO 和 RW? A:因为 RO 中的指令和常量以及 RW 中初始化过的变量是不能像 ZI 那样“无中 生有”的。 ARM 程序的执行过程 从以上两点可以知道,烧录到 ROM 中的 image 文件与实际运行时的 ARM 程序 之间并不是完全一样的。因此就有必要了解 ARM 程序是如何从 ROM 中的 image 到达实际运行状态的。 实际上,RO 中的指令至少应该有这样的功能: 1. 将 RW 从 ROM 中搬到 RAM 中,因为 RW 是变量,变量不能存在 ROM 中。 2. 将 ZI 所在的 RAM 区域全部清零,因为 ZI 区域并不在 Image 中,所以需要 程序根据编译器给出的 ZI 地址及大小来将相应得 RAM 区域清零。ZI 中也是变 量,同理:变量不能存在 ROM 中 在程序运行的最初阶段,RO 中的指令完成了这两项工作后 C 程序才能正常访问 变量。否则只能运行不含变量的代码。 说了上面的可能还是有些迷糊,RO,RW 和 ZI 到底是什么,下面我将给出几个 例子,最直观的来说明 RO,RW,ZI 在 C 中是什么意思。
#include "stm32f10x_conf.h" #endif 看来,是这个 USE_STDPERIPH_DRIVER 没有被定义啊,于是,人为地去掉 条件: //#ifdef USE_STDPERIPH_DRIVER
#include "stm32f10x_conf.h" //#endif 再次编译,果然就 OK 了。可是,可是,也不能就这么去掉啊,怎么办呢?万能 的网啊,一搜果然就有了。
到设置 C/C++页面 在那个 define 中加入“USE_STDPERIPH_DRIVER,STM32F10X_HD” 当然,去掉条件编译前面的注释,回到原样。 再次编译,一切顺利。可是,原来的工程例子也没有加这个啊,怎么回事呢?再 次打开原来的例子,找到 stm32f10x.h,可以看到有这么一行:
用菜单 Project-->New uVision Porject...建立新的工程,选择目标器件为 STM3 2103VC,这个过程与建立 51 单片机的工程没有什么区别,这里就偷点懒,不 上图了。接下来看一看怎么设置。
点那个品字形,打开对话框
这里就给个图了,相信有一定操作基础的人应该会用。顺便提一下,原来用 VC 或者 IAR 时总觉得它们的一个功能:就是建立一个是 Debug 组和 Release 组, 这个功能挺好的,从这个图可在 Keil 里也是一样可以建的。 将刚才那个文件夹图中 CMSIS 中的文件加入 CMSIS 组,一共 3 个,其中\Sour ce\CMSIS\Core\CM3 有两个 C 语言源程序文件全部加入,另外还有一个在 \Source\CMSIS\Core\CM3\startup\arm 文件夹中,这个文件夹中有 4 个.s 文 件,我们选择其中的 startup_stm32f10x_hd.s 文件。这是根据项目所用 CPU 来 选择的,我们用的 CPU 是 103VC 的,属于高密度的芯片,所以选这个。 至于 LIB 中的文件,就在这儿:\Source\STM32F10x_StdPeriph_Driver\src 啦。 这里有很多个文件,把什么文件加进去呢?怕麻烦的话,把所有文件全部加进去, 这并不会增加编译后的代码量,但会增加很多的编译时间。
相关文档
最新文档