完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1、c语言基础。
①运算符。 基本算数运算符:+、-、*、/、%:加、减、乘、除、取余。 关系运算符:<、>、==、!=、>=、<=:小于、大于、等于、不等于、大于等于、小于等于。 逻辑运算符:&&、||,!:逻辑与、逻辑或、逻辑非。 按位运算符:&、|、^、~、<<、>>:位与、位或、位异或、位非、左移、右移。 A…不改变其他位的值的情况,对某几位进行设置。 设置的位先&0,再|需要设置的值。 GPIOA->&=0XFFFFFF0F; //第4到7位清零 GPIOA->|=0X00000040; //第4到7位设置对应的值。 B…提高代码可读性。 GPIOx->BSRR=(((uint32_t)0x01)< GPIOA->ODR |= 1<<5; //PA.5输出高,其他位不变 C…取反操作使用技巧。 SR寄存器每一位代表一个状态,设置某一位为0其他位为1。 TIMx->SR = 0XFFF7; //第3位设置为0,可读性差 库函数是如下操作的: #define TIM_FLAG_Update ((uint16_t)0X0001) //宏定义 TIMx_SR = (uint16_t)~TIM_FLAG_Update; //设置宏定义的一位为0,其他为1 ②宏定义。 #define 标识符 字符串 //宏定义 标识符是定义的宏名,代替后面的字符串 #define SYSCLK_FREQ_72MHz 72000000 //用SYSCLK_FREQ_72MHz代替72000000,提高可读性 ③条件编译。 #ifdef 标识符 程序段1 #else 程序段2 #endif 如果标识符已经定义过,对程序段1进行编译,否则对程序段2进行编译,也可以没有#else #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" .............................................. .............................................. #endif ④extern外部变量。 extern可以放在变量或者函数前,表示该变量或者函数在别的文件夹中有定义。 变量:A.c文件中要使用B.c文件中的变量(int a),方法一:在A.c文件中extern int a;,方法二:定义B.h,B.h中声明变量extern int a;,A.c文件中引用头文件#include"B.h"。 函数:A.c文件中要使用B.c文件中的函数int fun(void) {return 0;},方法一:A.c文件中声明int fun(void);或者extern int fun(void);方法二:定义B.h,B.h中声明extern int fun(void);或者int fun(void);。 ⑤typedef 类型别名。 一般结构是:typedef 原类型名 新类型名; 例如:typedef unsigned int uint; struct GPIO{…}; //struct GPIO定义结构体变量 typedef struct{…}GPIO_InitDef; //GPIO_InitDef可以用来定义结构体变量。比上面的简洁。 ⑥结构体。 struct 结构体名{成员变量}; 声明和定义分开进行。 struct student{char name; int age;}; struct student student1,student2; 声明和定义在一起。 struct student{char name; int age}student1,student2; //其他地方还能通过struct student定义结构体变量 声明和定义在一起,且其他地方不能定义结构体变量。 struct{char name; int age}student1,student2; 结构体成员变量的引用方法: 结构体变量名.成员名 例如:student1.age; struct *student3; //定义一个结构体指针 (*student3).name = A; //结构体指针指向结构体成员 student3->age = 10; //结构体指针指向结构体成员 (p).成员名 == p->成员名 //由于结构体成员运算符优先级高于指针运算符,所以圆括号不能省略 "."结构体成员运算符 ""指针运算符 "()"圆括号,优先级最高 "->"指向结构体成员运算符 2、STM32系统架构。 STM32主系统主要由四个驱动单元和四个被动单元构成。 驱动单元:内核DCode总线、系统总线、DMA1、DMA2。 被动单元:AHB到APB的桥,连接所有的APB设备、FLASH、SRAM、FSMC。 几个总线知识: ①ICode总线:该总线将M3内核指令总线和闪存指令接口相连。 ②DCode总线:该总线将M3内核数据总线和闪存数据接口相连。 ③系统总线:该总线将M3内核系统总线和总线矩阵相连,总线矩阵协调内核和DMA的访问。 ④DMA总线:该总线将DMA和总线矩阵相连,总线矩阵协调内核的DCode和DMA到SRAM、闪存和外设的访问。 ⑤总线矩阵:内核系统总线和DMA主控总线的仲裁,连接在总线上的主单元:DCode总线、系统总线、DMA1总线、DMA2总线,连接在总线上的从单元:Flash、SRAM、FSMC、AHB2APB桥。 ⑥AHB2APB桥:AHB(高级高性能总线advanced high-performance bus)和APB(高级外设总线advanced peripheral bus)通过AHB2APB桥相连,APB1操作速度限于36MHz,APB2操作速度全速(up to 72MHz depending on the device)。 3、STM32时钟系统。 时钟系统是CPU的脉搏,就像人的心跳一样。 51单片机一个系统时钟就可以解决一切,STM32为什么要有多个时钟源? 原因1:STM32本身复杂,外设多,不是所有的外设都需要系统时钟这么高的频率,如看门狗。 原因2:同一个电路,时钟越快功耗越大,同时抗电磁干扰的能力也会越弱。STM32五个时钟源: HSI:high speed internal 高速内部时钟 RC 8MHz HSE:high speed external 高速外部时钟 4-16MHz LSI:low speed internal 低速内部时钟 40KHz LSE:low speed external 低速外部时钟 32.768KHz PLL:phase locked loop 锁相环(输入源是HSE、HSE/2、HSI/2,可以2-16倍倍频输出,最高不得超过72MHz)。 ①MCO(PA8)是STM32的时钟输出,可以选择PLL/2、HSI、HSE、SYSCLK。 ②RTC时钟源可以选择LSE、LSI、HSE/128。 ③STM32有一个全速USB模块,USB模块需要48MHz时钟源,只能通过PLL 1分频、1.5分频,需要使用USB模块时,PLL必须使能,PLL时钟源要配置成48MHz或72MHz。 ④SYSCLK系统时钟选择HSE、HSI、PLL,系统时钟最大时钟频率是72MHz。 ⑤外设时钟来源于系统时钟。 外设模块包含: AHB总线、内核、内存、DMA的HCLK时钟。 8分频后给Cortex的系统定时器时钟,也就是systick。 给Cortex的空闲时钟FCLK。 给APB1分频器,PCLK1最高36MHz。 给APB2分频器,PCLK2最高72MHz。 STM32时钟系统的配置除了在初始化时再system_stm32f10x.c中的SystemInit()函数外,其他配置主要在stm32f10x_rcc.c文件中。 库函数中,.s的启动文件中有这么一段: ; Reset handler //汇编里面注释用; Reset_Handler PROC //定义一个子程序Reset_Handler,PROC是伪指令 EXPORT Reset_Handler [WEAK] //表示Reset_Handler这个子程序可以被其他模块调用 IMPORT __main IMPORT SystemInit //表示__main和SystemInit这两个标号在其他文件,在链接的时候需要到其他文件中寻找 LDR R0, =SystemInit //SystemInit地址加载到寄存器R0 BLX R0 //程序跳到R0执行 LDR R0, =__main //__main地址加载到寄存器R0 BX R0 //程序跳到R0执行,执行完成后就去到了我们熟悉的c世界 ENDP //子程序结束 SystemInit在库文件system_stm32f10x.c中实现,用来初始化STM32的时钟 __main其实不是我们定义的,当编译器编译时,只要遇到这个标号就会定义这个函数,这个函数的功能主要是:负责初始化栈、堆,配置系统环境,并在最后跳转到用户自定义的main函数,从此来到c的世界。 上面涉及了两个寄存器RCC_CR和RCC_CFGR,分别是时钟控制寄存器和时钟配置寄存器,这段代码实现了时钟的初始化,默认即可,继续往下看: /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ /* Configure the Flash Latency cycles and enable prefetch buffer */ SetSysClock(); 1 2 3 这里有一个时钟设置函数,看一下它的实现函数: static void SetSysClock(void) { #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz SetSysClockTo72(); #endif /* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */ } 我们需要去找宏定义,system_stm32f10x.c中有如下条件编译: #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 #endif 我们在建立工程的时候,魔术棒–C/C++中添加了STM32F10X_HD,USE_STDPERIPH_DRIVER的宏定义,所以这里默认的是72MHz。 我们再仔细分析SetSysClockTo72()函数: 以下代码摘自标准外设库文件system_stm32f10x.c,且将互联型相关代码删除,程序流程为: 开启HSE,等待HSE稳定。 设置APB2、APB1、AHB分频系数。 设置PLL时钟来源和PLL倍频系数。 开启PLL,等待PLL稳定。 读取时钟切换状态,确保PLLCLK被选为系统时钟。 static void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; //1.使能HSE RCC->CR |= ((uint32_t)RCC_CR_HSEON); //等待HSE稳定,StartUpCounter用于超时处理判断标志 do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); //若HSE稳定,HSEStatus = 0x01 if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else //HSE超时了还没稳定 { HSEStatus = (uint32_t)0x00; } //2. HSE启动成功 if (HSEStatus == (uint32_t)0x01) { //使能flash预存储缓冲区,flash设置相关 FLASH->ACR |= FLASH_ACR_PRFTBE; FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; //不分频SYSCLK, HCLK = SYSCLK RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //不分频HCLK, PCLK2 = HCLK RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //2分频HCLK, PCLK1 = HCLK / 2 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; //3. 设置PLL时钟来源、PLL倍频因素为9,即PLLCLK等于8M * 9 = 72M RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); //4. 使能PLL RCC->CR |= RCC_CR_PLLON; //等待PLL稳定 while((RCC->CR & RCC_CR_PLLRDY) == 0); //5. 选择PLL作为系统时钟源 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //读取时钟切换状态成功标志位 while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08); } else { //HSE启动失败,用户可以编程作出提示 } } ST官方库提供的库函数,默认使用的是外部8MHz晶振,如果我们替换为12MHz,需要修改如下(STM32F10x_StdPeriph_Lib_V3.4.0为例): ①打开stm32f10x.h,将 #define HSE_VALUE ((uint32_t)8000000) 1 修改为: #define HSE_VALUE ((uint32_t)12000000) 1 ②打开system_stm32f10x.c,修改PLL参数,将 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | CC_CFGR_PLLMULL9); 修改为: RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | CC_CFGR_PLLMULL6); ③到现在,如果您直接编译调试的话,就会出现上文所说的USART的波特率不正确,Systick走时不准等问题,原因就是我们需要进行第三步的修改,这个修改不是在原文件中,而是在编译环境中。我们已Keil MDK为例说明。 打开你已经建立的STM32工程,选择Projects-〉Options for target ***,找到Target标签,你会发现,外接的晶振默认还是8MHz,我们将外接的晶振参数修改为12MHz,确定保存,再编译,调试,你就会发现,所有的参数都回归的正常轨道,设置波特率为9600,它也不会跑到14400,设置Systick为1ms中断,它不会1.5ms中断。 库函数中SystemInit()函数中设置的系统时钟大小: SYSCLK(系统时钟) = 72MHz AHB总线时钟(使用SYSCLK时钟) = 72MHz APB1总线时钟(APB1) = 36MHz APB2总线时钟(APB2) = 72MHz PLL时钟 = 72MHz 4、端口复用和重映射。 STM32有很多内置外设,这些外设引脚都是与GPIO复用的。也就是说一个GPIO可以复用为外设的引脚,当GPIO作为内置外设的时候,叫做端口复用。 PA9和PA10默认是GPIO,也可以当做外设USART1引脚的TX和RX。 端口复用的步骤: ①GPIO端口时钟使能。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); ②复用的外设时钟使能。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); ③端口模式配置。 GPIO配置为外设引脚时,需要根据"中文参考手册"的外设的GPIO配置,配置GPIO模式,上图是USART的GPIO引脚配置。 //USART1_TX PA9推挽复用输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //引脚设置 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度设置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //模式设置 GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA10浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //引脚设置 GPIO_InitStructure.Mode = GPIO_Mode_IN_FLOATING; //模式设置 GPIO_Init(GPIOA, &GPIO_InitStructure); 我们使用复用功能是需要设置至少两个时钟:GPIO时钟和外设时钟。 STM32中有很多内置外设的引脚可以复用到不同的GPIO,叫做重映射Remap。 重映射指的是UART1可以复用到PB6和PB7。 步骤如下: ①使能GPIO时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); ②使能外设时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); ③使能AFIO时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); ④开启重映射。 GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE); 这样就把USART1的TX和RX重映射到PB6和PB7上面了。 USART3有部分重映射和完全重映射。 GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE); //部分重映射 GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE); //完全重映射 5、STM32的NVIC中断优先级管理。 CM3内核支持256个中断,其中16个内核中断和240个外部中断。 STM32并没有使用CM3内核的全部东西,只用了一部分。 STM32有84个中断,16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。 STM32F103有60个中断,STM32F107有68个中断。 NVIC是内嵌向量中断控制器,Nested Vectored Interrupt Controller。 typedef struct { __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */ uint32_t RESERVED0[24]; __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */ uint32_t RSERVED1[24]; __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */ uint32_t RESERVED2[24]; __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */ uint32_t RESERVED3[24]; __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */ uint32_t RESERVED4[56]; __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644]; __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */ } NVIC_Type; NVIC_Type; STM32的中断在这些寄存器的控制下有序执行,了解这些寄存器才能方便的使用STM32的中断。 ISER:中断使能寄存器组,interrupt set-enable registers,8个32为寄存器控制256个中断,STM32F103只有60个中断,所以只用到ISER[0]和ISER[1],每一位置1即可使能对应的中断。 ICER:中断使能寄存器组,interrupt clear-enable registers,与ISER对应,写1可以清楚对应的中断。NVIC的这些寄存器都是写1有效。 ISPR:中断挂起控制寄存器组,interrupt set-pending registers,置1可以将正在进行的中断挂起,而执行同级别或更高级别的中断,写0无效。 ICPR:中断解挂控制寄存器组,interrupt clear-pending registers,与ISPR对应,写1可以将挂起的中断解挂,写0无效。 IABR:中断激活标志寄存器组,interrupt active bit registers,只读寄存器组,如果是1表示该位对应的中断正在执行,中断执行完硬件自动清零。 IP:中断优先级控制寄存器组,interrupt priority registers,240个8bit寄存器组,每个可屏蔽占8bit,共240个可屏蔽中断。STM32只用到前60个,IP[59]-IP[0]。8bit没有全用,只用了高4位,这4位又分为抢占优先级和子优先级。抢占优先级和子优先级各占几位由SCB->AIRCR中的中断分组设置来决定。 SCB->AIRCR寄存器的bit10-8定义分组。 例如设置为组3,则抢占优先级3bit,子优先级1bit,抢占优先级可以设置为0-7,子优先级可设置为0-1,抢占优先级的级别高于子优先级。 NVIC中断管理函数主要在misc.c文件里面。 中断优先级分组函数: void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) { assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; } #define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ #define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ #define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ #define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ #define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ #define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || ((GROUP) == NVIC_PriorityGroup_1) || ((GROUP) == NVIC_PriorityGroup_2) || ((GROUP) == NVIC_PriorityGroup_3) || ((GROUP) == NVIC_PriorityGroup_4)) 中断优先级分组函数只能调用一次,一旦分组确定就最好不要更改。 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置组2,2bit抢占优先级,2bit子优先级。 确定中断优先级分组之后,对每个中断进行抢占优先级和子优先级的设置。 中断初始化函数声明如下: void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStructure) 其中NVIC_InitTypeDef是一个结构体,如下: typedef struct { uint8_t NVIC_IRQChannel; uint8_t NVIC_IRQChannelPreemptionPriority; uint8_t NVIC_IRQChannelSubPriority; FunctionalState NVIC_IRQChannelCmd; } NVIC_InitTypeDef; 成员变量的作用是: NVIC_IRQChannel是每个中断对应的名字,如USART1_IRQn。 NVIC_IRQChannelPreemptionPriority是抢占优先级的级别。 NVIC_IRQChannelSubPriority是子优先级的级别。 NVIC_IRQChannelCmd是是否使能。 串口1中断的初始化方法: NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级为1 NVIC_InitStructure.NVIC-IRQChannelSubPriority = 2; //子优先级为2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); 中断优先级设置步骤:①NVIC_PriorityGroupConfig();中断优先级分组。②NVIC_Init();中断初始化。 6、MDK中寄存器地址名称映射分析。 ①51单片机开发中经常会引用 reg51.h 的头文件,名字和寄存器联系起来: sfr P0 = 0x80; sfr 是一种扩充数据类型,可以把名字P0和寄存器0x80对应起来。 P0 = value;就是在寄存器0x80中写入value。 ②STM32也可以参考51的设计,但STM32寄存器太多太多,列出来不方便,也显得太杂乱无章。MDK采用的方式是通过结构体将寄存器组织在一起,通过修改结构体成员变量的值就可以达到操作寄存器的值。这些事情实在stm32f10x.h文件中完成。 举例GPIOA的几个寄存器: 表中GPIOA的7个寄存器都是32位的,地址偏移是00h-18h,这个地址偏移是相对GPIOA的基地址而言的,GPIOA是挂在APB2总线上的,APB2总线基地址+GPIOA在APB2总线上的偏移地址即是GPIOA的基地址。stm32f10x.h中的GPIO_TypeDef定义如下: typedef struct { _IO uint32_t CRL; _IO uint32_t CRH; _IO uint32_t IDR; _IO uint32_t ODR; _IO uint32_t BSRR; _IO uint32_t BRR; _IO uint32_t LCKR; } GPIO_TypeDef; //CRL、CRH、IDR、ODR、BSRR、BRR、LCKR是地址连续的 #define GPIOA ((GPIO_TypeDef*)GPIOA_BASE); 7、MDK固件库快速组织代码技巧。 GPIO八中模式是枚举类型: type enum { GPIO_Mode_AIN = 0x1, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x2, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_PP = 0x18 } GPIOMode_TypeDef; //枚举类型中的变量都是用逗号隔开的,最后一个变量后面没有逗号 GPIO的初始化: GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1786 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1622 浏览 1 评论
1089 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
730 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1941浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
739浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
573浏览 3评论
598浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
560浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 09:55 , Processed in 1.057491 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号