keil-C语言-单片机STM32U575实现UART控制LED灯的开关
今日练习:keil-C语言-单片机STM32U575实现UART控制LED灯的开关,由于使用了STM32CubeMX工具,关于UART和GPIO相关的初始化配置已经简化,本次只有实现功能代码,共勉
学习小结:
计算机的组成-输入设备、输出设备、控制器、运算器、存储器;
机器指令-机器码,由多个0和1组成,可由多个汇编指令组成的指令集编译而成,通过原理图及芯片手册定位芯片上各I/O口相关寄存器地址,并通过配置寄存器对各类I/O口进行配置,实现通过软件对硬件的控制;
指令集分为RISC(精简指令集-将使用频繁和简单的指令生成指令集,追求功能的特定性,每条指令长度固定,执行周期固定)和CISC(复杂指令集-将几乎所有能包含的功能都集成到一起的指令集,指令集长度不固定,执行周期也不固定);
单片机在start时,底层代码先配置“异常向量表”,对应5中异常模式(1.SVC 2.UNDEF 3.ABORT 4.IRQ 5.FIQ)下的7种异常源(1.复位 2.未定位 3.软中断 4.指令异常 5.数据异常 6.低优先级中断 7.高优先级中断);
栈内存读写-栈类型(1.空栈 2.满栈 3.增栈 4.减栈),组合栈(空增栈EA 空减栈ED 满增栈FA 满减栈FD),对于栈内存的现场保护中,需要注意后缀ia是空增栈,后缀ib是空减栈,后缀da是满增栈,后缀db是满减栈,但与组合栈不同,后缀ia用于压栈只能用db来出栈,而后缀FD可以同时用于压栈和出现(不深究的话可以直接用组合栈后缀,因为学习的板子的缘故,用的是后缀FD);
汇编语言与c语言间相互调用的用法;
STM32CubeMX的学习,以UI的图形界面方式通过对需要的外设进行选择设置,快速生成STM32基本可执行代码,完成相关的外设的初始化功能,大大减轻了STM32裸板开发的难度。
GPIO(通用输入输出)在单片机中的工作原理及如何通过寄存器进行相关配置(通过原理图及芯片手册,找到GPIO及其时钟总线RCC,使能时钟以及GPIO_EN,配置GPIOx_MODER,GPIOx_OTYPER,GPIOx_OSPEEDR,GPIOx_PUPDR,GPIOx_IDR,GPIOx_ODR...,GPIO的基本配置至少是这些);STM32U575单片机GPIO驱动的私人理解-CSDN博客
UART(通用异步接收器/发送器)在单片机中的工作原理及如何通过寄存器进行相关配置(通过原理图及芯片手册,找到UART及其时钟总线RCC和UART对应的GPIO口,使能时钟以及GPIO_EN和UART_EN,配置GPIOx_MODER复用,GPIOx_IDR,GPIOx_ODR,USARTx_C1,USARTx_C2,USARTx_BRR,USARTx_ISR,USARTx_RDR,USARTx_TDR,USARTx_PRESC...);STM32U575单片机UART驱动的私人理解-CSDN博客
以上是本周学习的小结。
今日练习:keil-C语言-单片机STM32U575实现UART控制LED灯的开关
基本思路:通过UART与PC端通信,当UART接收到PC端的数据(LED1_ON)时,单片机控制LED1对应的GPIO输出高电平,反之当UART接收到PC端的数据(LED1_OF)时,单片机控制LED1对应的GPIO输出低电平。
本次练习分了两种规则,代码中可查看,需要注意由于规则二中接收的数据长度不通,需要先以帧头的数据为首先接收的长度。
#include "main.h"
#include "icache.h"
#include "usart.h"
#include "gpio.h"
#include "string.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
SystemPower_Config();
MX_GPIO_Init(); //GPIO初始化
MX_USART1_UART_Init(); //USART1初始化
MX_ICACHE_Init();
uint8_t ch_buf[128] = {0}; //定义一个接收UART数据的buf
HAL_StatusTypeDef ch_type = HAL_OK; //定义一个接收UART函数的返回值
HAL_UART_Transmit(&huart1, "Start\n\r", strlen("Start\n\r"), 5); //上电先发送一个Start提示
while (1)
{
memset(ch_buf, 0, sizeof(ch_buf)); //清空buf
#if 0 //规则一:发送字符‘1’或‘0’控制LED1的开关,每次只决定一个字节值,使用==即可
ch_type = HAL_UART_Receive(&huart1, ch_buf, 1, 10000); //每次只接收一个字节长度的数据
if (ch_type == HAL_OK)
{
if (ch_buf[0] == '1') //接收到字符‘1’时,控制PC4高电平,并发送LED1_ON给PC端
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, "LED1_ON\n\r", strlen("LED1_ON\n\r"), 5);
}
else if (ch_buf[0] == '0') //接收到字符‘0’时,控制PC4低电平,并发送LED1_OFF给PC端
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_UART_Transmit(&huart1, "LED1_OFF\n\r", strlen("LED1_OFF\n\r"), 5);
}
else //接收到非‘1’和非‘0’时,发送字符串LED1_ERR给PC端
{
HAL_UART_Transmit(&huart1, "LED1_ERR\n\r", strlen("LED1_ERR\n\r"), 5);
}
}
else if (ch_type == HAL_TIMEOUT && (strlen(ch_buf) > 0)) //当有数据但是长度不够导致超时时,提示超时
{
HAL_UART_Transmit(&huart1, "TIMEOUT\n\r", strlen("TIMEOUT\n\r"), 5);
}
#else //规则二:发送字符串"LED1_ON"或"LED1_OFF"控制LED1的开关,需要比较字符串,使用strcmp即可,这里需要注意由于规则中接收的数据长度不通,需要先以帧头的数据为首先接收的长度。
ch_type = HAL_UART_Receive(&huart1, ch_buf, 7, 10000);//先接收7个字节长度的数据
if (ch_type == HAL_OK)
{
if (!strcmp(ch_buf, "LED1_ON")) //当接收到的字符串数据为"LED1_ON"时,控制PC4高电平,并发送LED1_ON给PC端
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, "LED1_ON\n\r", strlen("LED1_ON\n\r"), 5);
}
else if (!strcmp(ch_buf, "LED1_OF")) /当接收到的字符串数据为"LED1_OF"时,需要继续接收1个字节
{
ch_type = HAL_UART_Receive(&huart1, ch_buf+7, 1, 10000);
if (ch_type == HAL_OK)
{
if (*(ch_buf+7) == 'F') //将接收到的数据组合为"LED1_OFF"时,控制PC4低电平,并发送LED1_OFF给PC端
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_UART_Transmit(&huart1, "LED1_OFF\n\r", strlen("LED1_OFF\n\r"), 5);
}
else //若只有"LED1_OF",则发送字符串LED1_ERR给PC端
{
HAL_UART_Transmit(&huart1, "LED1_ERR\n\r", strlen("LED1_ERR\n\r"), 5);
}
}
}
else //接收到非"LED1_ON"和非"LED1_OFF"时,发送字符串LED1_ERR给PC端
{
HAL_UART_Transmit(&huart1, "LED1_ERR\n\r", strlen("LED1_ERR\n\r"), 5);
}
}
else if (ch_type == HAL_TIMEOUT && (strlen(ch_buf) > 0)) //当有数据但是长度不够导致超时时,提示超时
{
HAL_UART_Transmit(&huart1, "TIMEOUT\n\r", strlen("TIMEOUT\n\r"), 5);
}
#endif
}
}
更多推荐



所有评论(0)