[{"content":"STM32介绍 基于ARM Cortex-M内核开发的32位微控制器\nSTM32F103C8T6 内核：ARM Cortex-M3 主频：72MHz RAM：20K(SRAM) ROM：64K(Flash) 供电：2.0~3.6V(标准3.3V) 封装：LQFP48 片上资源/外设 NVIC嵌套向量中断控制器：内核里面用于管理中断的设备，比如配置中断优先级 SysTick系统滴答定时器：内核里的定时器，给操作系统（如FreeRTOS、UCOS）提供定时服务，定时进行任务切换的功能 RCC复位和时钟控制：外设在上电的情况下默认没有时钟，不给时钟情况下，操作无效，外设也不会工作，这样的目的是降低功耗。所以在操作外设前要先操作时钟，使用RCC完成时钟的使能。 GPIO通用IO口 AFIO复用IO口：完成复用功能端口的重定义，还有中断端口的配置 EXTI外部中断：配置好外部中断后，当引脚有电平变化时，可以触发中断，让CPU来处理任务 TIM定时器：高级定时器、通用定时器、基本定时器，不仅可以完成定时中断，还可以完成测频率、生成PWM波形、配置成专用的编码器接口等 ADC模数转换器：STM32内置了12位的AD转换器，可以直接读取IO口的模拟电压值，无需外部连接AD芯片 DMA直接内存访问：帮助CPU完成大量数据搬运功能 USART同步/异步串口通信 I2C通信、SPI通信：通信协议 CAN通信：一般用于汽车领域 RTC实时时钟：在STM32内部完成年月日、时分秒的计时功能，且可以接外部备用电池，即使掉电也能正常运行 CRC校验：用于判断数据的正确性 PWR电源控制：可以让芯片进入睡眠模式等状态，来达到省电的目的 BKP备份寄存器：存储器，当系统掉电时，仍可由备用电池保持数据 IWDG独立看门狗、WWDG窗口看门狗：当单片机因为电磁干扰死机或者程序设计不合理出现死循环时，看门狗可以及时复位芯片，保持系统稳定 DAC数模转换器，可以在IO口直接输出模拟电压 FSMC可变静态存储控制器：用于扩展内存，或者配置成其他总线协议，用于某些硬件操作 USB OTG：USB主机接口，用OTG功能，可以让STM32作为USB主机去读取其他USB设备 系统结构 左上方Cortex-M3内核，引出3条总线，ICode指令总线、DCode数据总线、System系统总线，ICode与DCode主要用于连接Flash闪存，Flash里是编写的程序，ICode用来加载程序指令，DCode用来加载数据，System系统总线连接到其他上面，比如SRAM存储程序运行数据，AHB（先进高性能总线）系统总线用于挂在主要的外设，APB（先进外设总线）用于连接一般外设，由于AHB和APB的总线协议、总线速度、还有数据传送格式的差异，所以中间需要加两个桥接，来完成数据的转换和缓存。 DMA可看作内核CPU的小秘书，比如一些大量的数据搬运。DMA通过DMA总线连接到总线矩阵上，可以拥有和CPU一样的总线控制权，用于访问这些外设。当需要DMA搬运数据时，外设就会通过请求线发送DMA请求，然后DMA就会获得总线控制权，访问并转运数据， 整个过程无需CPU的参与。 引脚定义 红色是电源相关引脚，蓝色是最小系统相关引脚，绿色是IO口、功能口引脚\n启动配置 一般情况下，程序都是在Flash程序存储器开始执行，但是某些情况下可以让程序在别的地方开始执行，用来完成特殊的功能。\n最小系统电路 新建工程 建立工程文件夹，keil中新建工程、选择型号 工程文件夹中建立Start、Library、User等文件夹，复制固件库中的文件到工程文件中 工程里对应建立Start、Library、User等同名称的分组，然后将文件夹内的文件添加到工程分组里 工程选项，C/C++，Include Paths内声明所有包含头文件的文件夹 工程选项，C/C++，Define内定义USE_STDPERIPH_DRIVER 工程选项，Debug，下拉列表选择对应调试器，Settings，Flash Download里勾选Reset and Run 工程架构 C语言 宏定义 关键字：#define 用途：用一个字符串代替一个数字，便于理解防止出错；提取程序中经常出现的参数，便于快速修改 定义宏定义：#define ABC 12345 引用宏定义：int a = ABC；//等效int a = 12345； typedef 用途：将一个比较长的变量类型名换个名字，便于使用 定义：typedef unsigned char uint8_t; 引用 ：uint8_t a;//等效于unsigned char a； 结构体 关键字：struct 用途：数据打包，不同类型变量的集合 定义结构体变量 struct{char x;int y;float z;} StructName; 因为结构体变量类型较长，所以通常用typedef更改其变量类型名 引用结构体成员： StructName.x = \u0026lsquo;A\u0026rsquo;； pStructName-\u0026gt;x = \u0026lsquo;A\u0026rsquo;；//pStructName为结构体的地址 枚举 关键字：enum 用途：定义一个取值受限制的整形变量，用于限制变量取值范围；宏定义的集合 定义枚举变量：enum{FALSE = 0 , TRUE = 1} EnumName; 引用枚举成员：EnumName = FALSE; GPIO GPIO简介 General Purpose Input Output通用输入输出口 可配置为8种输入输出模式 引脚电平0-3.3V，部分引脚可容忍5V 输出模式下可控制端口输出高低电平，用来驱动LED、控制蜂鸣器、模拟通信协议输出时序 输入模式下可读取端口的高低电平或电压，用于读取按键输入，外界模块电平信号输入、ADC电压采集、模拟通信协议接收数据 GPIO 基本结构 在STM32中，所有GPIO都挂载在APB2外设总线上，其中GPIO名称按照GPIOA、GPIOB\u0026hellip;\u0026hellip;.来标注，每个GPIO外设总共有16个引脚从0到15。\n寄存器是特殊的存储器，内核可以通过APB2总线对寄存器进行读写，这样可以完成输出电平和读取电平的功能。寄存器的每一位对应一个引脚，其中输出寄存器写1，对应的引脚就会输出高电平，反之输出低电平；输入寄存器读取为1，就证明对应的端口目前是高电平，反之为低电平。由于STM32为32位的单片机，所以STM32内部的寄存器都是32位的，但是端口只有16位，该寄存器只有低16位对应的有端口，高16位没用到。寄存器只负责存储数据，如要进行其他操作，还需要驱动器来负责增大驱动能力。\nGPIO位结构 左侧为三个寄存器，中间为驱动器，右侧为某一个IO口的引脚。\n整体可分为两个部分，上面为输入部分，下面为输出部分。VDD、VSS的两个开关，是为了给输入提供一个默认的输入电平（上拉、下拉、浮空），因为对应一个数字的端口，输入不是高电平就是低电平，如果浮空，引脚的输入电平会受外界干扰而改变。上拉输入可称作是默认为高电平的输入模式，下拉输入是默认为低电平的输入模式。\n输入部分：\nTTL肖特基触发器，其实就是施密特触发器，对输入电压进行整形，当输入电压大于某一阈值，输出电压为高电平，当输入电压小于某一阈值，输出电压为低电平。可以有效避免因信号波动造成的输出抖动现象。\n经过施密特触发器整形的波形可以直接写入输入数据寄存器了，再用程序读取输入寄存器对应某一位的数据，就可以知道端口的输入电平。\n模拟输入连接到ADC上，因为ADC需要接受模拟量，所以要接触发器前面。\n复用功能输入是连接到其他需要读取端口的外设上的，接触发器后面。\n**输出部分：**由输出数据寄存器和片上外设控制\n两种控制方式通过数据选择器连接到了输出控制部分，如果选择通过输出数据寄存器进行控制，就是普通的IO口输出，写这个数据寄存器的某一位就可以操作对应的某个端口了。\n位设置/清除寄存器，可以单独操作输出数据寄存器的某一位，而不影响其他位。因为这个输出数据寄存器同时控制16个端口，并且这个寄存器只能整体读写，所以如果想单独控制其中某一个端口而不影响其他端口，需要特殊的操作方式（按位与、设置位设置/清除寄存器）。\n通过信号来控制MOS管开关的导通和关闭，开关负责将IO口接到ADD或者VSS，可选择推挽、开漏或关闭三种输出方式。①在推挽输出模式下，PMOS和NMOS均有效，数据寄存器位1时，上管导通下管断开，输出直接接到VDD，就是输出高电平，反之输出低电平。在此模式下，STM32对IO口具有绝对的控制权。②在开漏输出模式下，PMOS无效，只有NMOS在工作，数据寄存器为1时，输出相当于断开也就是高阻模式，数据寄存器为0时，下管导通，输出直接接到VSS，也就是低电平。这种模式下，只有低电平有驱动能力，高电平没有驱动能力。可作为通信协议的驱动方式，在多机通信的情况下，这个模式可以避免各个设备的相互干扰，另外还可用于输出5V的电平信号③在关闭模式下，是当引脚配置为输入模式时，两个MOS管都无效，端口的电平由外部信号来控制。\n8种工作模式 模式名称 性质 特征 浮空输入 数字输入 可读取引脚电平，若引脚悬空，则电平不确定 上拉输入 数字输入 可读取引脚电平，内部连接上拉电阻，悬空时默认高电平 下拉输入 数字输入 可读取引脚电平，内部连接下拉电阻，悬空时默认低电平 模拟输入 模拟输入 GPIO无效，引脚直接接入内部ADC 开漏输出 数字输出 可输出引脚电平，高电平为高阻态，低电平接VSS 推挽输出 数字输出 可输出引脚电平，高电平接VDD，低电平接VSS 复用开漏输出 数字输出 由片上外设控制，高电平为高阻态，低电平接VSS 复用推挽输出 数字输出 由片上外设控制，高电平接VDD，低电平接VSS 浮空输入、上拉输入、下拉输入的电路结构基本一致，区别就是上拉电阻和下拉电阻的连接。在输入模式下，输出驱动器断开，只能输入而不能输出\n模拟输入，是ADC模数转换器的专属配置，输出断开，输入的施密特触发器也是关闭的无效状态\n开漏/推挽输出的区别在于高电平，开漏是高阻态，推挽是VDD\n复用开漏/推挽输出的结构如下，都由片上外设控制\n常用函数以及样例 初始化样例 1 2 3 4 5 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,\u0026amp;GPIO_InitStructre); GPIO_Init需要输入两个参数，第一个参数是指定GPIOx（其中X可以为A\u0026hellip;G），第二个参数是一个指向GPIO_InitTypeDef结构的指针，因此我们还需要定义一个结构体，通过GPIO_InitTypeDef的方式定义，定义后需要对三个参数进行设置：\nGPIO_Mode设置：也就是对工作模式进行选择，模拟输入AIN、浮空输入IN_FLOATING、下拉输入IPD、上拉输入IPU、开漏输出Out_OD、推挽输出Out_PP、复用开漏输出AF_OD、复用推挽输出AF_PP GPIO_Pin设置：也就是对引脚进行选择，可以从GPIO_Pin_0~GPIO_Pin_15，共16个引脚，也可以使用GPIO_Pin_All对所有引脚进行选择，也可以使用或(|)的方式进行选择，GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2，使用此方式对引脚012进行选择 GPIO_Speed设置：输出速度可选择GPIO_Speed_10MHz,GPIO_Speed_2MHz,GPIO_Speed_50MHz 按样例定义完成后，GPIOB外设的12号引脚就自动被配置为推挽输出、50MHz的速度了，它内部的主要执行逻辑就是读取结构体的参数，执行判断和运算，最后写入到GPIO配置寄存器中\n输出操作 常用的四个操作如下\n1 2 3 4 void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); SetBits完成对某GPIO外设的某引脚置1 ResetBits完成对某GPIO外设的某引脚置0 WriteBit(GPIOx,GPIO_Pin_X,Bit_SET/Bit_RESET) Write第一个参数是选定一个GPIO外设，第二个参数是一个4位16进制数，为16个二进制，对应着16个端口，最低位为PA0，如0x0001对应0000 0000 0000 0001即Pin0置1,0x0003对应0000 0000 0000 0011即Pin0\\Pin1置1 输入操作 按键介绍 按键：常见的输入设备，按下导通，松手断开\n按键抖动：由于按键内部使用的是机械式弹簧片来进行通断的，所以在按下和松手的瞬间会伴有一连串的抖动\n初始化按键可采用上拉输入IPU\n1 2 3 4 5 6 7 8 9 10 11 12 13 uint8_t Key_GetNum(void) { uint8_t KeyNum = 0; if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0) { Delay_ms(20); while (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0); Delay_ms(20); KeyNum = 1; } if.......//按其他端口，KeyNum为其他值 return KeyNum; } 传感器介绍 传感器元件的电阻会随外界模拟量的变化而变化，通过与定值电阻分压即可得到模拟电压输入，再通过电压比较器进行二值化即可得到数字电压输出\n硬件电路 下接按键方式（通常普遍采用）\n若采用左侧方式，必须采用上拉输入，否则会出现引脚悬空，输出不确定\n上接按键方式\n连接方式：VCC接3.3V提供电源，GND接地，DO数字输出随便接一个端口，用于读取数字量，AO模拟输出。\n传感器端口可采用上拉输入IPU\n输入代码 带有Bit是只读取一个位，无Bit是读取一整个的，每一个都以0/1表示\n1 2 3 4 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); OLED 样例\n函数 作用 OLED_Init(); 初始化 OLED_Clear(); 清屏 OLED_ShowChar(1, 1, \u0026lsquo;A\u0026rsquo;); 显示一个字符 OLED_ShowString(1, 3, \u0026ldquo;HelloWorld!\u0026rdquo;); 显示字符串 OLED_ShowNum(2, 1, 12345, 5); 显示十进制数字 OLED_ShowSignedNum(2, 7, -66, 2); 显示有符号十进制数字 OLED_ShowHexNum(3, 1, 0xAA55, 4); 显示十六进制数字 OLED_ShowBinNum(4, 1, 0xAA55, 16); 显示二进制数字 中断系统 中断概念 中断：在主程序运行进程中，出现了特定的中断触发条件，使得CPU暂停当前正在运行的程序，转而去处理中断程序，处理完成后又返回原来被暂停的位置继续运行 中断优先级：当有多个中断源同时申请中断，CPU会根据中断源的轻重缓急进行裁决，优先响应更加紧急的中断源 中断嵌套：当一个中断程序正在运行时，又有新的更高优先级的中断源申请中断，CPU再次暂停当前中断程序，转而去处理新的中断程序，处理完成后依次进行返回 STM32中断 68个可屏蔽中断通道，包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设 使用NVIC统一管理中断，每个中断通道都有16个可编程的优先等级，可对优先级进行分组，进一步设置抢占优先级和响应优先级 NVIC基本结构 NVIC的中断优先级由优先级寄存器的4位（0~15）决定，这4位可以进行切分，分为高n位的抢占优先级和低4-n位的响应优先级 抢占优先级高的可以中断嵌套，响应优先级高的可以优先排队，抢占优先级和响应优先级均相同的按中断号排队 分组方式 抢占优先级 响应优先级 分组0 0位，取值为0 4位，取值为0~15 分组1 1位，取值为0~1 3位，取值为0~7 分组2 2位，取值为0~3 2位，取值为0~3 分组3 3位，取值为0~7 1位，取值为0~1 分组4 4位，取值为0~15 0位，取值为0 EXTI外部中断 EXTI可以监测指定GPIO口的电平信号，当其指定的GPIO口产生电平变化时，EXTI将立即向NVIC发出中断申请，经过NVIC裁决后即可中断CPU主程序，使CPU执行EXTI对应的中断程序 支持的触发方式：上升沿/下降沿/双边沿/软件触发 支持的GPIO口：所有GPIO口，但相同的Pin不能同时触发中断 通道数：16个GPIO_Pin，外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒 触发响应方式：中断响应/事件响应（中断响应是正常的流程，引脚电平变化触发中断；事件响应不会触发中断，而是触发别的外设操作，属于外设之间的联合工作） 旋转编码器 旋转编码器：用来测量位置、速度或旋转方向的装置，当其旋转轴旋转时，其输出端可以输出与旋转速度和方向对应的方波信号，读取方波信号的频率和相位信息即可得知旋转轴的速度和方向 类型：机械触点式/霍尔传感器式/光栅式 基本流程 RCC时钟启用\n1 2 3 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//启用GPIOB RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//启用AFIO //EXTI与NVIC本身时钟就启用，无需启动 GPIO端口配置\n1 2 3 4 5 GPIO_InitTypeDef GPIO_InitStructure;//定义结构体 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,\u0026amp;GPIO_InitStructure);//初始化 AFIO引脚选择\n1 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//14脚使用GPIOB的Pin14 EXTI配置\n1 2 3 4 5 6 EXTI_InitTypeDef EXTI_InitStructure;//定义结构体 EXTI_InitStructure.EXTI_Line = EXTI_Line14;//启用14引脚 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断响应 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 EXTI_Init(\u0026amp;EXTI_InitStructure);//初始化 NVIC配置\n1 2 3 4 5 6 7 NVIC_InitTypeDef NVIC_InitStructure;//定义结构体 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组形式，2位抢占、2位响应 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//指定要启用的通道 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级 NVIC_Init(\u0026amp;NVIC_InitStructure);//初始化 NVIC配置后，可配置中断响应函数\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 //对射式红外传感器计次 void EXTI15_10_IRQHandler(void)//名称与通道名对应 { if(EXTI_GetITStatus(EXTI_Line14) == SET) { CountSensor_Count++; Delay_ms(20); EXTI_ClearITPendingBit(EXTI_Line14); } } ------------------------------------------------------------ //旋转编码器计次 int16_t Encoder_Get(void) { int16_t Temp; Temp = Encoder_Count; Encoder_Count = 0; return Temp; } void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) == SET) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0) Encoder_Count --; EXTI_ClearITPendingBit(EXTI_Line0);\t} } void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) == SET) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0) Encoder_Count ++; EXTI_ClearITPendingBit(EXTI_Line1);\t} } TIM定时器 简介 定时器可以对输入的时钟进行计数，并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元，在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能，而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型 类型 编号 总线 功能 高级定时器 TIM1、TIM8 APB2 拥有通用定时器全部功能，并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 通用定时器 TIM2、TIM3、TIM4、TIM5 APB1 拥有基本定时器全部功能，并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 基本定时器 TIM6、TIM7 APB1 拥有定时中断、主模式触发DAC的功能 STM32F103C8T6定时器资源：TIM1、TIM2、TIM3、TIM4 基本计时器只支持向上计数，通用定时器和高级定时器支持向上计数、向下计数、中央对齐三种模式 定时中断基本结构如下\n预分频器时序如下（PSC）\n计数器计数频率：CK_CNT = CK_PSC / (PSC + 1)\n计数器时序如下（ARR）\n计数器溢出频率：CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1)\n计数器无预装与有预装时序\n定时中断 RCC使能\n1 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); 内部时钟模式\n1 TIM_InternalClockConfig(TIM2);//内部时钟 时基单元\n1 2 3 4 5 6 7 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义结构体 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数模式 TIM_TimeBaseInitStructure.TIM_Period = 10000-1;//周期 TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;//预分频器 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重计数值 TIM_TimeBaseInit(TIM2,\u0026amp;TIM_TimeBaseInitStructure); 使能中断\n1 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//更新时触发中断 NVIC\n1 2 3 4 5 6 7 NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(\u0026amp;NVIC_InitStructure); 启动定时器\n1 TIM_Cmd(TIM2,ENABLE); 外部时钟 RCC使能\n1 2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO配置\n1 2 3 4 5 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,\u0026amp;GPIO_InitStructure); 外部时钟模式设置\n1 TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0f); 时基单元配置\n1 2 3 4 5 6 7 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 10-1; TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2,\u0026amp;TIM_TimeBaseInitStructure); 使能中断\n1 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); NVIC配置\n1 2 3 4 5 6 7 NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(\u0026amp;NVIC_InitStructure); 启动定时器\n1 TIM_Cmd(TIM2,ENABLE); 输出比较 OC(Output Compare)输出比较 输出比较可以通过比较CNT与CCR寄存器值的关系，来对输出电平进行置1、置0或翻转的操作，用于输出一定频率和占空比的PWM波形\n每个高级定时器和通用定时器都拥有4个输出比较通道\n高级定时器的前3个通道额外拥有死区生成和互补输出的功能\nPWM脉冲宽度调制 在具有惯性的系统中，可以通过对一系列脉冲的宽度进行调制，来等效地获得所需要的模拟参量，常应用于电机控速等领域\n参数：频率 = 1 / TS 占空比 = TON / TS 分辨率 = 占空比变化步距\n输出比较通道\n输出比较模式\n模式 描述 冻结 CNT=CCR时，REF保持为原状态 匹配时置有效电平 CNT=CCR时，REF置有效电平 匹配时置无效电平 CNT=CCR时，REF置无效电平 匹配时电平翻转 CNT=CCR时，REF电平翻转 强制为无效电平 CNT与CCR无效，REF强制为无效电平 强制为有效电平 CNT与CCR无效，REF强制为有效电平 PWM模式1 向上计数：CNT\u0026lt;CCR时，REF置有效电平，CNT≥CCR时，REF置无效电平向下计数：CNT\u0026gt;CCR时，REF置无效电平，CNT≤CCR时，REF置有效电平 PWM模式2 向上计数：CNT\u0026lt;CCR时，REF置无效电平，CNT≥CCR时，REF置有效电平向下计数：CNT\u0026gt;CCR时，REF置有效电平，CNT≤CCR时，REF置无效电平 PWM基本结构\n参数计算\nPWM频率：Freq = CK_PSC / (PSC + 1) / (ARR + 1) PWM占空比：Duty = CCR / (ARR + 1) PWM分辨率：Reso = 1 / (ARR + 1) LED呼吸灯 内部时钟配置\n1 TIM_InternalClockConfig(TIM2); 时基单元\n1 2 3 4 5 6 7 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 100-1;//ARR TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1;//PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2,\u0026amp;TIM_TimeBaseInitStructure); 输出比较单元\n1 2 3 4 5 6 7 TIM_OCInitTypeDef TIM_OCinitStructure; TIM_OCStructInit(\u0026amp;TIM_OCinitStructure);//给结构体赋初始值 TIM_OCinitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式 TIM_OCinitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//极性 TIM_OCinitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能 TIM_OCinitStructure.TIM_Pulse = 50;//CCR的值 TIM_OC1Init(TIM2,\u0026amp;TIM_OCinitStructure); GPIO\n1 2 3 4 5 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(GPIOA,\u0026amp;GPIO_InitStructure); 启动定时器\n1 TIM_Cmd(TIM2,ENABLE); 控制PMW调亮度\n1 2 3 4 void PWM_SetCompare1(uint16_t Compare) { TIM_SetCompare1(TIM2,Compare); } 舵机 舵机是一种根据输入PWM信号占空比来控制输出角度的装置\n输入PWM信号要求：周期为20ms，高电平宽度为0.5ms~2.5ms\nPMW配置：内部时钟配置\u0026mdash;\u0026mdash;时基单元\u0026mdash;\u0026mdash;输出比较单元\u0026mdash;\u0026mdash;GPIO\u0026mdash;\u0026mdash;启动定时器 舵机角度函数配置 直流电机 直流电机是一种将电能转换为机械能的装置，有两个电极，当电极正接时，电机正转，当电极反接时，电机反转\n直流电机属于大功率器件，GPIO口无法直接驱动，需要配合电机驱动电路来操作\nTB6612是一款双路H桥型的直流电机驱动芯片，可以驱动两个直流电机并且控制其转速和方向\nPMW配置：内部时钟配置\u0026mdash;\u0026mdash;时基单元\u0026mdash;\u0026mdash;输出比较单元\u0026mdash;\u0026mdash;GPIO\u0026mdash;\u0026mdash;启动定时器 电机配置：复用推挽输出配置GPIO\u0026mdash;\u0026mdash;速度配置函数 输入捕获 IC（Input Capture）输入捕获 输入捕获模式下，当通道输入引脚出现指定电平跳变时，当前CNT的值将被锁存到CCR中，可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数 每个高级定时器和通用定时器都拥有4个输入捕获通道 可配置为PWMI模式，同时测量频率和占空比 可配合主从触发模式，实现硬件全自动测量 测频率 测频法：在闸门时间T内，对上升沿计次，得到N，则频率f_x=N / T 测周法：两个上升沿内，以标准频率fc计次，得到N ，则频率f_x=f_c / N 中界频率：测频法与测周法误差相等的频率点f_m=√f_c / T 测频法要求信号频率高一些，测周法要求信号频率低一些。都存在±1误差\n测占空比 ","permalink":"https://hangzz0910.github.io/posts/tech/stm32/","summary":"STM32介绍 基于ARM Cortex-M内核开发的32位微控制器 STM32F103C8T6 内核：ARM Cortex-M3 主频：72MHz RAM：20K(SRAM) ROM：64K(Flash) 供电：2.0~3.6V(标准3.3V) 封装：LQFP48 片上资源/外设 NVIC嵌套向量中断控制器：内核里面用于管理中断的设备，比如","title":"STM32基础"},{"content":"我为什么想搭建博客 我也不知道嘿嘿，用Southernwood小朋友的话来说就是“装逼！”\n其实很早之前就有想搭自己博客的打算，虽然我不是一个很爱用文字来记录的人，但是互联网总归来说是有记忆的，传至互联网的数据有时候回想起来可能也是一种美好的回忆吧。\n除此之外呢，就是室友都在搭建博客，而且之后准备打一下服务外包的比赛，在其中应该能积累一些项目经验和一些技术吧，到时候也可以写成个人博客让互联网帮我记忆😋😋\n重启博客计划 在我搭建博客之前，我根本不知道我需要哪些技术，或是说要使用到什么技术，然后得知可以采用hugo或者hexo框架来搭建，但是依然是Southernwood小朋友跟我说的，很多人从hexo框架转成了hugo框架，虽然我也不知道是什么原因，那我也就啥也不想了，直接从hugo入手了。\n一开始跟着B站上的CodeSheep的视频搭建（后续在我搭建辛酸过程中还会讲到），然后想切换成Stack主题，但是Stack主题好像很多东西要自己来修改，我也只是个屁也不懂的菜狗，我改不来，然后就开始放弃了，很久一段时间就没再管博客这件事。直到10月30日这天，当天十分头晕带着点头痛，我就不想学习，但是又不想浪费时间，于是乎决定重启我的博客计划。\n我又重新在hugo官方网站上面找新的theme，由于个人比较喜欢简约一点的主题，看到了papermod这种极简式风格的主题，就决定采用此主题了。有了主题之后就是考虑是采用GitHub代理还是租个服务器和域名挂到服务器上，最后刚好赶上了阿里云在云栖大会上提出的天工开物高校计划，可以领取300元无门槛的代金券，我拿着代金券租了6个月的轻量应用服务器，后续应该还会继续续租，并买了我很喜欢的域名hangzz.cn。但是因为域名备案需要半个月左右时间，在我域名备案好之前，是采用GitHub代理的，现在你所看到的已经是域名备案好挂在阿里云服务器上的。下面我会先讲采用GitHub代理，后续再讲挂到个人阿里云服务器上，其中可能会少了某些步骤，因为我也有点忘了👉👈如果遇到问题了，请个人搜索互联网，通过互联网都能解决问题。\n我的hugo框架博客搭建过程 下面我以Windows系统为例展示\n1.安装hugo 首先到hugo官网下载相应版本\n下载完成后检查是否安装成功，在cmd内输入hugo version，若出现版本信息则表示安装成功。 2.新建站点 找一个合适的文件夹，输入hugo new site myblog,(此处的myblog可以更改为你想要的文件名),就会在myblog文件夹内出现如下目录结构 3.下载主题 先去hugo官方网站上面找到你心仪的主题，然后点击Download就会跳转到相对应主题的github仓库。\n可以采用git clone的方式，将github仓库上的内容下载下来可以省去压缩包解压缩的过程。（如果要采用git clone的方式，就需要将）\n首先输入cd myblog以及cd themes将终端路径调整到博客文件夹的themes目录下，由于我的主题为PaperMod，输入git clone https://github.com/adityatelange/hugo-PaperMod.git ，然后themes文件夹下面便会出现如下目录：\n若想使用该主题的方法就是在站点文件夹的config配置文件中输入主题的名字\n1 theme: PaperMod # 主题名字，与themes文件夹下相一致 4.配置文件 站点配置文件采用.yaml后缀的写法，看说法是更适合阅读，由于我也是copy来的，也不大懂，详细可看hugo官方文档，下面是我的config.yaml的配置\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 baseURL: \u0026#34;https://www.hangzz.cn/\u0026#34; # 绑定的域名 languageCode: zh-cn # en-us title: 杭の小屋 theme: PaperMod # 主题名字，和themes文件夹下的一致 enableInlineShortcodes: true enableEmoji: true # 允许使用 Emoji 表情，建议 true enableRobotsTXT: true # 允许爬虫抓取到搜索引擎，建议 true hasCJKLanguage: true # 自动检测是否包含 中文日文韩文 如果文章中使用了很多中文引号的话可以开启 buildDrafts: false buildFuture: false buildExpired: false googleAnalytics: # 谷歌统计 # Copyright: Sulv paginate: 5 # 首页每页显示的文章数 summaryLength: 140 # 文章概览的自字数，默认70 minify: disableXML: true # minifyOutput: true permalinks: # 访问博客时网址的显示形式 post: \u0026#34;/:title/\u0026#34; # post: \u0026#34;/:year/:month/:day/:title/\u0026#34; defaultContentLanguage: zh # 最顶部首先展示的语言页面 defaultContentLanguageInSubdir: false menu: main: - identifier: search name: 🔍 搜索 url: search weight: 1 - identifier: home name: 🏠 主页 url: / weight: 2 - identifier: posts name: 📚 文章 url: posts weight: 3 - identifier: tags name: 🧩 标签 url: tags weight: 15 - identifier: archives name: ⏱️ 时间轴 url: archives/ weight: 20 - identifier: about name: 🙋🏻‍♂️ 关于 url: about weight: 50 - identifier: links name: 🤝 友链 url: links weight: 60 outputs: home: - HTML - RSS - JSON # 这里的参数会被代码以 .Site.Params 的形式读取 params: env: production # to enable google analytics, opengraph, twitter-cards and schema. description: \u0026#34;\u0026#34; author: Hang # author: [\u0026#34;Me\u0026#34;, \u0026#34;You\u0026#34;] # multiple authors defaultTheme: dark # defaultTheme: light or dark disableThemeToggle: false DateFormat: \u0026#34;2006-01-02\u0026#34; ShowShareButtons: true ShowReadingTime: true # disableSpecialistPost: true displayFullLangName: true ShowPostNavLinks: true ShowBreadCrumbs: true ShowCodeCopyButtons: true hideFooter: false # 隐藏页脚 ShowWordCounts: true VisitCount: true ShowLastMod: true #显示文章更新时间 ShowToc: true # 显示目录 TocOpen: true # 自动展开目录 extendCodeBackground: false # 代码块是否自动横向展开 comments: true profileMode: enabled: true title: 杭の小屋 # subtitle: # subtitle: \u0026#34;\u0026#34; imageUrl: \u0026#34;/img/H.jpg\u0026#34; imageTitle: imageWidth: 150 imageHeight: 150 buttons: - name: 🧱 建站 url: posts/blog - name: 👨🏻‍💻 技术 url: posts/tech # - name: 📕 阅读 # url: posts/read - name: 🏖 生活 url: posts/life socialIcons: - name: github url: \u0026#34;https://github.com/HangZz0910\u0026#34; # - name: twitter # url: \u0026#34;img/twitter.png\u0026#34; # - name: facebook # url: \u0026#34;https://www.facebook.com/profile.php?id=100027782410997\u0026#34; # - name: instagram # url: \u0026#34;img/instagram.png\u0026#34; # - name: QQ # url: \u0026#34;img/qq.png\u0026#34; # - name: WeChat # url: \u0026#34;img/wechat.png\u0026#34; # - name: bilibili # url: \u0026#34;https://space.bilibili.com/234461224\u0026#34; # - name: email # url: \u0026#34;mailto:202203151103@zjut.edu.cn\u0026#34; # - name: RSS # url: \u0026#34;index.xml\u0026#34; label: # 左上角图标 text: \u0026#34;Hang\u0026#39;s Blog\u0026#34; icon: \u0026#34;/img/H.jpg\u0026#34; iconHeight: 40 analytics: google: SiteVerificationTag: \u0026#34;\u0026#34; assets: favicon: \u0026#34;/img/H.jpg\u0026#34; favicon16x16: \u0026#34;/img/H.jpg\u0026#34; favicon32x32: \u0026#34;/img/H.jpg\u0026#34; apple_touch_icon: \u0026#34;/img/H.jpg\u0026#34; safari_pinned_tab: \u0026#34;/img/H.jpg\u0026#34; disableFingerprinting: true # 禁用指纹 cover: hidden: false # hide everywhere but not in structured data hiddenInList: false # hide on list pages and home hiddenInSingle: false # hide on single page fuseOpts: # 搜索配置 isCaseSensitive: false shouldSort: true location: 0 distance: 1000 threshold: 0.4 minMatchCharLength: 0 keys: [\u0026#34;title\u0026#34;, \u0026#34;permalink\u0026#34;, \u0026#34;summary\u0026#34;] StartYear: 2023 # 底部开始年份 FilingNo: 浙ICP备2023039216号-1 # 底部备案号 # PublicSecurityIconLink: 填自己的公安图标链接 # 填自己的公安图标链接,可用绝对路径，相对路径如 img/beian.png # PublicNetworkSecurity: 填自己的公网安备 # 底部公网安备号 Reward: false #打赏是否开启 # 打赏微信图片地址， # 可用绝对和相对地址，相对地址的图片需放在static/img下， # 填写格式为img/wechat_pay.png # WechatPay: img/wechat_pay.png # Alipay: img/alipay.png #打赏支付宝图片地址 # twikoo评论 twikoo: version: 1.6.22 # 填写twikoo版本号 id: https://twikoo-api-rho-virid.vercel.app/ # 填写自己的twikoo id region: # 环境地域，默认为 ap-shanghai，如果您的环境地域不是上海，需传此参数，请看twikoo官方文档 taxonomies: category: categories tag: tags series: series markup: goldmark: renderer: unsafe: true # HUGO 默认转义 Markdown 文件中的 HTML 代码，如需开启的话 highlight: # anchorLineNos: true codeFences: true guessSyntax: true # lineNos: true noClasses: true tabWidth: 4 style: monokai # codeFences：代码围栏功能，这个功能一般都要设为 true 的，不然很难看，就是干巴巴的-代码文字，没有颜色。 guessSyntax: true #猜测语法，这个功能建议设置为 true, 如果你没有设置要显示的语言则会自动匹配。 # hl_Lines：高亮的行号，一般这个不设置，因为每个代码块我们可能希望让高亮的地方不一样。 lineNoStart: 1 #行号从编号几开始，一般从 1 开始。 lineNos: 1 #：是否显示行号，我比较喜欢显示，所以我设置的为 true. # lineNumbersInTable：使用表来格式化行号和代码,而不是 标签。这个属性一般设置为 true. # noClasses：使用 class 标签，而不是内嵌的内联样式 privacy: vimeo: disabled: false simple: true twitter: disabled: false enableDNT: true simple: true instagram: disabled: false simple: true youtube: disabled: false privacyEnhanced: true services: instagram: disableInlineCSS: true twitter: disableInlineCSS: true 5.写文章 输入hugo new 文章名称.md就会在content目录下生成“文章名称.md”名字的文件，所有文章都会放在content文件夹中，可以采用各类markdown编辑器进行编辑。\n6.启动博客 终端路径调整至 myblog文件夹下输入hugo server后就可以在本地进行预览，本地预览地址为localhost:1313。如果顺利的话，你已经可以看到自己本地的博客了，由于距离我建站已经有一段时间了，详细的忘得差不多了，如果碰到什么问题的话，希望都能通过互联网来解决。\n7.将博客部署到github上 这部分需要使用到一个叫做github page的东西，是GitHub提供的一个网页寄存服务，可以寄存静态页面，这个特性就特别适合博客的搭建。\n首先再Github上创建一个 Repository，命名为Github名字，譬如我github用户名为hangzz0910，那么仓库名就为hangzz0910.github.io，这样就可以生成一个用户页面\n在hugo server调试页面完成后，使用命令hugo生成hugo静态页面，在执行命令后，会出现一个public文件夹，这就是网站的静态页面文件\n进入public文件夹，使用git上传文件\n1 2 3 4 5 6 cd public git init ##初始化仓库 git remote add origin https://github.com/HangZz0910/hangzz0910.github.io.git ##链接远程仓库 git add . git commit -m \u0026#34;first commit\u0026#34; git push -u origin master 在此之后更新文章，使用hugo生成新的静态页面，并使用git push进行同步\n1 2 3 4 5 cd public git add . git status git commit -m \u0026#34;add blog post\u0026#34; git push 提示：commit -m后面的东西是此次提交的备注，通常用来说明提交人的名字\n如果顺利的话，现在输入用户名.github.io就可以进行访问，但是由于github服务器架设在国外，直接访问速度会比较慢，这也就是我采用租赁国内云服务器的原因之一。\n8.将博客部署到阿里云服务器 ①前置条件 购买服务器和个人喜欢的域名，服务器可以看一下阿里云的天工开物高校计划，可以领取300元无门槛的代金券，还是十分划算的，我的域名是29一年，算下来的话其实成本并不高。\n如果hugo博客部署到GitHub那么不需要备案，因为GitHub属于国外服务器，但是用大陆的服务器就需要进行备案，备案可以看各自域名备案流程，我在阿里云备案大概花了十天左右时间，其中就只是阿里云客服打过一次电话，其他就只要等就行了。\n②服务器下载nginx 进入阿里云控制台登陆服务器，确保centos有sudo权限，输入sudo -l 确保80端口(http)和443端口(https)没用被占用，如果没有显示任何结果则说明没有被占用\n1 2 sudo netstat -tulpn | grep :80 sudo netstat -tulpn | grep :443 安装nginx/设置开机启动nginx/启动nginx/查看是否启动nginx，按次序在控制台输入如下四句语句\n1 2 3 4 sudo yum install -y nginx sudo systemctl enable nginx sudo systemctl start nginx sudo systemctl status nginx 这几步完成后，在浏览器搜索框输入您的服务器公网IP地址，如果会出现nginx的页面，说明可以导航到您的服务器，即nginx安装成功\n③防火墙设置 为了使外部用户可以访问web服务器，需要开放防火墙，主要是80端口和443端口，可以在服务器的控制台手动设置开启 ④将静态网页上传至服务器 通过hugo命令可以生成一个public文件夹，这就是网页上展示的东西\n现在要做的事情就是把public文件夹里面的内容传送到服务器上，不过需要先在服务器里面建一个public文件夹，我选择建在了home文件夹内\n上传文件我采用的是一种比较笨的方法，利用vscode的插件remote-ssh，用vscode与服务器进行链接，至于remote-ssh的链接方法，就不再赘述，链接成功后将myblog内的所有内容都直接上传至服务器上的public文件夹即可，后续可以在vscode内直接对博客进行编辑，只需要hugo一下就可以直接上传服务器。\n我采用vscode的还有一个原因就是，我不会vim命令，用vscode可以让我使用比较方便\n⑤申请ssl证书 为了让网站更加安全，首先申请一下https的ssl证书，购买了服务器可以免费申领证书，然后下载这个证书。\n我们只需要nginx文件夹里面的私钥对文件，因为在nginx的配置文件里面配置https的时候需要用到，把这两个公秘钥文件上传至服务器的/etc/nginx目录里，因为nginx的配置文件也在这个目录下，方便调用。\n⑥配置nginx的nginx.conf文件 下面是我的配置文件，可以相对应地进行改动即可\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 # 要配置的第一个地方，这里的用户要改成root，不然可能会没有权限 user root; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main \u0026#39;$remote_addr - $remote_user [$time_local] \u0026#34;$request\u0026#34; \u0026#39; \u0026#39;$status $body_bytes_sent \u0026#34;$http_referer\u0026#34; \u0026#39; \u0026#39;\u0026#34;$http_user_agent\u0026#34; \u0026#34;$http_x_forwarded_for\u0026#34;\u0026#39;; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { # 要配置的第二个地方，80访问端口 listen 80 default_server; listen [::]:80 default_server; # 要配置的第三个地方，域名 server_name www.hangzz.cn; rewrite ^(.*) https://$server_name$1 permanent; # 要配置的第四个地方，这里指向public文件夹 root /home/public/public; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; # 要配置的第五个地方 location / { root /home/public/public; index index.html index.htm; } # 要配置的第六个地方 error_page 404 /404.html; location = /40x.html { root /home/public/public; } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # server { listen 443 ssl; #http2 default_server; # listen [::]:443 ssl http2 default_server; # 要配置的第七个地方 server_name www.hangzz.cn; root /home/public/public; # 要配置的第八个地方 ssl_certificate /etc/nginx/www.hangzz.cn.pem; ssl_certificate_key /etc/nginx/www.hangzz.cn.key; # 要配置的第九个地方 ssl_session_timeout 10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers PROFILE=SYSTEM; # ssl_prefer_server_ciphers on; # Load configuration files for the default server block. # location / { # } # 要配置的第十个地方 error_page 404 /404.html; location = /40x.html { root /home/public/public; } # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } include /etc/nginx/default.d/*.conf; } } 其中端口 80 用于配置 http 服务，端口 443 用于配置 https 服务，这样就完成了nginx 的配置\n修改完成后重新加载配置文件 sudo nginx -s reload\n检查nginx服务的运行情况 sudo systemctl status nginx\n重启nginx服务 sudo systemctl restart nginx\n通过域名访问网站，如果出现博客首页，说明配置成功了，如果域名还没有备案成功，用ip地址访问也可以跳转到博客首页。\n致谢 至此，我的hugo+GitHub/阿里云服务器搭建内容正式结束，当然其中省去了很多内容，主要是我也记不太清，在我搭建过程中也遇到了很多问题困难，都是通过互联网解决的，我写的搭建过程可能比较简略，还请各位看官见谅👉👈希望我的个人经历能给你带来一些正向作用\n在我搭建过程中，Southernwood小朋友给予了我极大的帮助，帮我解决了很多技术上的问题，同时很多问题也都能在Sulv\u0026rsquo;s Blog上面找到解决方法，很感谢互联网的便利性\n","permalink":"https://hangzz0910.github.io/posts/blog/blog/","summary":"我为什么想搭建博客 我也不知道嘿嘿，用Southernwood小朋友的话来说就是“装逼！” 其实很早之前就有想搭自己博客的打算，虽然我不是一个很爱用文字来记录的人，但是互联网总归来说是有记忆的，传至互联网的数据有时候回想起来可能也是一种美好的回忆吧。 除此之外呢，就是室友都在搭建博客，","title":"我的hugo框架博客+GitHub/阿里云服务器搭建历程"},{"content":"\rSouthernwood\r小朋友\rMcola\r小可乐\rBoz\r小包子\r","permalink":"https://hangzz0910.github.io/links/","summary":"Southernwood 小朋友 Mcola 小可乐 Boz 小包子","title":"🤝友链"},{"content":"关于我\n姓名: Hang 职业: 平平无奇双非大二计科 运动: 户外 ","permalink":"https://hangzz0910.github.io/about/","summary":"关于我 姓名: Hang 职业: 平平无奇双非大二计科 运动: 户外","title":"🙋🏻‍♂️关于"}]