第一讲沁恒CH32V307————SayOhYeah
初识单片机
寄存器开发和标准库开发的区别
- 寄存器开发:需要开发者详细阅读芯片手册,了解每个寄存器的位含义,配置过程繁琐,容易出错,开发效率低,难度较高。
- 标准库开发:库函数通常有良好的命名和结构,配置外设只需调用相应的初始化函数,设置参数即可,开发效率高,难度较低。
结构体与数组之间的区别
数组是只可以申请一段同类型的地址进行存储
结构体可以申请的内存中可以存储不同类型的数据
GPIO的8中工作模式
- 输入浮空(Input Floating):引脚处于高阻态,即既不接上拉电阻也不接下拉电阻。输入电平完全由外部电路决定,适用于外部已经确定电平或者接有上拉/下拉电阻的情况。
- 输入上拉(Input Pull-up):内部接有上拉电阻,默认电平为高。当外部没有信号驱动时,引脚电平为高;外部拉低时,引脚电平为低。
- 输入下拉(Input Pull-down):内部接有下拉电阻,默认电平为低。当外部没有信号驱动时,引脚电平为低;外部拉高时,引脚电平为高。
- 模拟输入(Analog Input):将引脚设置为模拟输入模式,用于ADC(模数转换)或DAC(数模转换)等模拟功能。此模式下,引脚的数字输入功能被禁用,以减少功耗和干扰。
- 开漏输出(Open-Drain Output):输出晶体管仅接通到地(低电平),高电平靠外部上拉电阻拉高。这种模式可以实现电平转换(比如用3.3V控制5V设备)和总线连接(如I2C总线)。
- 推挽输出(Push-Pull Output):输出晶体管可以接通到高电平或低电平,能够直接驱动负载。这是最常用的输出模式,可以提供较强的驱动能力。
- 复用开漏输出(Alternate Function Open-Drain):当引脚用于外设功能(如I2C)时,工作于开漏模式。
- 复用推挽输出(Alternate Function Push-Pull):当引脚用于外设功能(如SPI、USART)时,工作于推挽模式。
如何使用标准库点亮一个LED灯
GPIO_InitTypeDef GPIO_InitStructure = {0};//定义一个gpio_InitTyprDef类型的结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//查找总线架构打开对应GPIO口的时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//在结构体中选择我们要使能的gpio口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//选择使能的gpio口的输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//选择gpio口的频率
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化gpio口
GPIO_SetBits(GPIOC, GPIO_Pin_2);//发出高电平
Delay_Ms(500);//延时500ms
GPIO_ResetBits(GPIOC, GPIO_Pin_2);//发出低电平
Delay_Ms(500);//延时500ms
如何使用标准库的定时器让LED闪烁
单片机主时钟频率为96兆(96 000 000)相当于一秒钟可以加96 000 000
void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));//定时器2快速中断
unsigned int time_1000ms;//中断计数值
unsigned char Led_Flag;//LED闪烁标志位
void Tim3_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitStruct.TIM_ClockDivision=0;//时钟分割
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//设置为向上计数
TIM_TimeBaseInitStruct.TIM_Period=arr;//自动重装载值,5000为500ms
TIM_TimeBaseInitStruct.TIM_Prescaler=psc;//设置分频值
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM3, TIM_IT_Update|TIM_IT_Trigger, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //打开中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update)!=RESET)
{
if(++time_1000ms==1000)
{
time_1000ms = 0;
Led_Flag =!Led_Flag;
if(Led_Flag)
{
GPIO_SetBits(GPIOC, GPIO_Pin_2);
}
else {
GPIO_ResetBits(GPIOC, GPIO_Pin_2);
}
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//
Tim3_Init(1000,96-1);//设置自动重装载值1秒进入一次设置分频值
while(1)
{
}
}
使用标准库的串口进行收发数据
-
配置串口三将串口3接收到的数据加一发送出来波特率是115200;
具体步骤
- 移植串口三的初始化函数
- 移植串口三的中断函数
- 声明快捷中断
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));//串口2快速中断
void Usart3_Init()//初始化usart3
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART3, ENABLE);
}
u8 usart3_state;
void USART3_IRQHandler(void)//开启串口中断
{
u8 temp;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
temp=USART_ReceiveData(USART3);
USART_SendData(USART3, temp+1);
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
Usart3_Init();
while(1)
{
}
}