文章目录
一.stm32外部中断模式控制灯亮灭
1.通过STMCube配置项目
(1)引脚配置图
(2)配置EXIT
(3)配置GPIO
(4)配置项目
2.通过KEIL配置代码
1.代码编写
当捕获到上升沿,触发中断,就会进入到这个函数里面
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
然后就会执行HAL_GPIO_EXTI_Callback(GPIO_Pin)函数,此函数为回调函数,我们打开可以发现前面有个weak。
前面的 __weak 表示此函数为虚函数,需要用户重写的。
那么我们在main.c文件中找个地方重新写一下。
位置在main函数下方。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if( GPIO_Pin == A1_EXTI_Pin)//判断外部中断源
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);//翻转LED状态
}
}
2.编译烧录
(1)编译
(2)烧录
3.电路图
LED长脚——3V3
LED短脚——PB5
PA1——3V3——亮灯
PA1——GND——熄灯
4.效果图
二、串口通讯输出hello
1.工程设置
(1)设置串口
点击USART1,设置MODE为异步通信,基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1,接收和发送都能,GPIO引脚设置 USART1_RX/USART_TX(这里一般自动设置好了)。 NVIC Settings 一栏使能接收中断
(2)时钟设置
2.代码编写
在main.c和usart.c中添加头文件#include “stdio.h”
之后,在usart.c文件中,添加如下代码,进行重定义
/* USER CODE BEGIN 1 */
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#if 1
//#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0x0001);
return ch;
}
#endif
/* USER CODE END 1 */
在main.c主函数中,添加发送数据
/* USER CODE END WHILE */
printf("Hello windows!\r\n");
HAL_Delay(500);
/* USER CODE BEGIN 3 */
在main.c中添加如下定义,用来接收串口数据
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[256]; //接收缓冲
uint8_t str1[20] = "s";
uint8_t str2[20] = "t";
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
uint8_t cAlmStr[] = "数据溢出(大于256)\r\n";
添加开启接收中断的语句
这里记得添加在主函数中,不是在外面
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */
在main.c下部添加中断回调函数
/* USER CODE BEGIN 4 */
/**
* @brief Rx Transfer completed callbacks.
* @param huart pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
if (strcmp(Uart1_RxBuff, str1) == 0) flag = 0;
if (strcmp(Uart1_RxBuff, str2) == 0) flag = 1;
//if(Uart1_RxBuff[0]=='g') flag = 1;
//if(Uart1_RxBuff[0]=='s') flag = 0;
if(Uart1_Rx_Cnt >= 255) //溢出判断
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
/* USER CODE END 4 */
3.编译烧录
(1) 编译
(2)烧录
三.stm32采用DAM方式向上位机发送数据
1.DMA简介
DMA的出现大大减轻了CPU的工作量。在硬件系统中,主要由CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常要在内存和外设之间,外设和外设之间转移。例如:CPU需要处理从外设采集回来的数据,CPU需要先将数据从ADC外设的寄存器读取到内存中(变量)去,然后进行运算处理,这是一般的解决方法。CPU的资源是非常宝贵的,我们可以设法把转移的工作交给其他部件来完成,CPU把更多的资源用于数据运算和中断响应上,如此DMA便登场了。DMA正是为CPU分担数据转移工作,因为DMA的存在,CPU才被解放出来,它可以在数据转移的同时进行数据运算,相应中断,大大提高了效率。普通模式:传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。\n循环模式:传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输
2.串口通信DMA传输完成中断
(1)步骤
(1)打开CUBRMX新建项目,芯片选择是F103C8,点击后创建项目;
(2)把PA9和PA10选择为USART1_RX和USART1_TX,然后再点击左边的USART1,将mode置为异步通信模式,我们这里只需要接收,不需要发送,后面再点击add键,添加引脚
(2)代码编写
Open Project 打开keil5,进入到main.c文件,在main.c文件中的while循环那块的代码如下:
while (1)
{
uint8_t send_char[]="hello world\n";//发送的字符串
HAL_UART_Transmit_DMA(&huart1,(uint8_t *)send_char,0xc);//DMA发送
HAL_Delay(500);//延时
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/80478882a04648de8e973baf8cc7455c.png#pic_center)
(3)实验结果
四.总结
DMA是一种在传输时不使用cpu的数据传输方式,可以节省cpu资源,提高CPU的利用率。对于DMA的串口发送函数HAL_UART_Transmit_DMA,需要size匹配你要发送的字符串。
五.参考文献
(1)STM32F103C8通过DMA方式向上位机连续发送信息
(2)stm32之串口通信DMA传输完成中断
(3)http://t.csdn.cn/G3sSD
(4)http://t.csdn.cn/hWgv9