实验一:点亮一个LED(跑马灯)
主函数
#include "sys.h"
#include "delay.h"
#include "led.h"
/*下面主函数是使用HAL库函数实现控制IO口输出*/
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
delay_init(96); //初始化延时函数
LED_Init(); //初始化LED
while(1)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);//LED0亮
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);//LED1灭
delay_ms(500); //延时500ms
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);//LED0灭
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);//LED1亮
delay_ms(500); //延时500ms
}
}
led.c
#include led.h
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1;//PC0~7
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0|GPIO_PIN_1,GPIO_PIN_SET); //PC0~7置1,默认初始化后灯灭
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
}
实验二:按键实验
主函数
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
int main(void)
{
vu8 key=0;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
delay_init(96); //初始化延时函数
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
while(1)
{
key=HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_8);
if(key==0)
{
delay_ms(10);//去抖动
while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_8)==0);
LED0=!LED0;
}
}
}
key.c
#include key.h
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9; //PC8,9
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
}
led部分同上。
实验三:串口实验
主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
int main(void)
{
u8 key=0;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
delay_init(96); //初始化延时函数
uart_init(115200); //初始化串口115200
KEY_Init();
while(1)
{
key=KEY_Scan(0);//得到键值
switch(key)
{
case KEY0_PRES://KEY0
printf("\r\n I LOVE SYAU\r\n");
break;
case KEY1_PRES://KEY1
printf("\r\n he he \r\n");
break;
}
}
}
usart.c
#include usart.h
u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄
//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound)
{
//UART 初始化设置
UART1_Handler.Instance=USART1; //USART1
UART1_Handler.Init.BaudRate=bound; //波特率
UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能UART1
HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
}
//UART底层初始化,时钟使能,引脚配置,中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART1; //复用为USART1
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
#if EN_USART1_RX
HAL_NVIC_EnableIRQ(USART1_IRQn); //使能USART1中断通道
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级3,子优先级3
#endif
}
}
key部分同上。
实验四:中断实验
主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "timer.h"
#include "exti.h"
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
EXTI_Init(); //初始化外部中断
delay_init(96); //初始化延时函数
uart_init(115200); //初始化串口115200
TIM3_Init(5000-1,9600-1); //10Khz的计数频率,计数5K次为500ms
while(1)
{
}
}
exti.c
#include "exti.h"
#include "delay.h"
//外部中断初始化
void EXTI_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
GPIO_Initure.Pin=GPIO_PIN_8; //PC8
GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发
GPIO_Initure.Pull=GPIO_PULLUP;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
//中断线8、9-PC8、9
HAL_NVIC_SetPriority(EXTI9_5_IRQn,2,1); //抢占优先级为2,子优先级为1
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
//中断服务函数
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); //调用中断处理公用函数
}
//中断服务程序中需要做的事情
//在HAL库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(10); //消抖
switch(GPIO_Pin)
{
case GPIO_PIN_8:
if(KEY0==0)
{
printf("\r\n 你必上岸! \r\n");
}
break;
}
}
timer.c
#include "timer.h"
#include "usart.h"
TIM_HandleTypeDef TIM3_Handler; //定时器句柄
//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!
void TIM3_Init(u16 arr,u16 psc)
{
TIM3_Handler.Instance=TIM3; //通用定时器3
TIM3_Handler.Init.Prescaler=psc; //分频系数
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM3_Handler.Init.Period=arr; //自动装载值
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
HAL_TIM_Base_Init(&TIM3_Handler);
HAL_TIM_Base_Start_IT(&TIM3_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE
}
//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)
{
__HAL_RCC_TIM3_CLK_ENABLE(); //使能TIM3时钟
HAL_NVIC_SetPriority(TIM3_IRQn,2,3); //设置中断优先级,抢占优先级1,子优先级3
HAL_NVIC_EnableIRQ(TIM3_IRQn); //开启ITM3中断
}
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM3_Handler);
}
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM3_Handler))
{
printf("\r\n 我要上岸! \r\n");
}
}
实验五:串口实验——多机通信
主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "exti.h"
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
delay_init(96); //初始化延时函数
LED_Init(); //初始化LED
uart_init(115200); //初始化串口115200
EXTI_Init();
while(1)
{
}
}
exti.c
#include "exti.h"
#include "delay.h"
#include "usart.h"
uint8_t dataToSend[] = "Hello, World!\n";
uint16_t dataSize = sizeof(dataToSend);
HAL_StatusTypeDef status;
//外部中断初始化
void EXTI_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
GPIO_Initure.Pin=GPIO_PIN_8; //PC8
GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发
GPIO_Initure.Pull=GPIO_PULLUP;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
//中断线8、9-PC8、9
HAL_NVIC_SetPriority(EXTI9_5_IRQn,3,1); //抢占优先级为2,子优先级为1
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
//中断服务函数
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); //调用中断处理公用函数
}
//中断服务程序中需要做的事情
//在HAL库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(10); //消抖
switch(GPIO_Pin)
{
case GPIO_PIN_8:
if(KEY0==0) //控制LED0翻转
{
HAL_UART_Transmit(&UART1_Handler, dataToSend, dataSize, 1000);
while((USART1 ->SR&0x40)==0);
}
break;
}
}
usart.c
usart.c的配置同上,再加上下面的代码:
u16 USART_RX_STA=0; //接收状态标记
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)//如果是串口1
{
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else
{
USART_RX_STA|=0x8000; //接收完成了
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//LED0反转
printf("GOT IT !\n");//输出
USART_RX_STA=0;//清除标志位
}
}
else //还没收到0X0D
{
if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
实验六:pwm
主函数
#include "sys.h"
#include "delay.h"
#include "pwm.h"
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(96,4,2,4); //设置时钟,96Mhz
delay_init(96); //初始化延时函数
TIM3_PWM_Init(1200-1,0); //不分频。PWM频率=96000/1200=80Khz
while(1)
{
}
}
pwm.c
#include "pwm.h"
TIM_HandleTypeDef TIM3_Handler; //定时器句柄
TIM_OC_InitTypeDef TIM3_CH1Handler; //定时器3通道1句柄
//TIM1 PWM部分初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
void TIM3_PWM_Init(u16 arr,u16 psc)
{
TIM3_Handler.Instance=TIM3; //定时器1
TIM3_Handler.Init.Prescaler=psc; //定时器分频
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
TIM3_Handler.Init.Period=arr; //自动重装载值
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//分频因子
HAL_TIM_PWM_Init(&TIM3_Handler); //初始化PWM
TIM3_CH1Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
TIM3_CH1Handler.Pulse=arr/2; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
TIM3_CH1Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低
HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH1Handler,TIM_CHANNEL_1);//配置TIM3通道1
HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_1);//开启PWM通道1
}
//定时器底层驱动,时钟使能,引脚配置
//此函数会被HAL_TIM_PWM_Init()调用
//htim:定时器句柄
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
if(htim->Instance==TIM3)
{
__HAL_RCC_TIM3_CLK_ENABLE(); //使能定时器3
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
GPIO_Initure.Pin=GPIO_PIN_6; //PA6
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
GPIO_Initure.Alternate= GPIO_AF2_TIM3; //PC6复用为TIM3_CH1
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
}
//设置TIM3通道1的占空比
//compare:比较值
void TIM_SetTIM3Compare1(u32 compare)
{
TIM3->CCR1=compare;
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM3_Handler);
}
IIC目前笔者还没研究透,示例代码过于繁琐,暂不展示,需要的同学还请先自行学习,望谅解。
上述代码仅是实现实验课要求的主要部分代码,仅供参考,例程已经过简化,酌情填写实验报告,如有不合适的地方还请见谅。