串口通信(stm32F4)——通过串口助手发送led on或者led off控制LED灯的亮灭

1. 实验目的

通过串口助手发送led on来点亮LED灯,发送led off来关闭LED灯(这里是LED1,其端口是GPIOF,引脚是PIN10,串口是USART1,其端口是GPIOA,引脚是PIN9、PIN10,一个用来收数据,一个用来发收据)

2. 实验流程

初始化LED;
初始化串口;
编写接收数据中断函数;
编写空闲中断函数。

2.1 初始化LED

//初始化GPIO端口
void LED_GPIO_Config(void)
{
	//初始化结构体 GPIO_InitStruct
	//里面是GPIO的速度,上下拉,输出类型
	 GPIO_InitTypeDef   GPIO_InitStruct;
	//打开时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);  //使能时钟必须放到前面,不然后面的操作不会使灯点亮
	//驱动是哪个引脚  PF10
	GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_10;
	//推挽输出
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	//上拉
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP ;
	//输出的速度
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	//变量获取它的指针,取地址就行(&)
	GPIO_Init(GPIOF,&GPIO_InitStruct);
	GPIO_SetBits(GPIOF,GPIO_Pin_10);  //GPIOF10设置高,灯灭
}

2.2 初始化串口

//配置中断函数,这个函数下面有调用
 void EXTI_NVIC_Config(void){
	//NVIC初始化结构体
	NVIC_InitTypeDef  NVIC_InitStruct;
	//设置中断优先级的分组
	//就是设置主抢占优先级和子抢占优先级各是几,这里是分组为1,代表主优先级可以是0和1(就是1个位来设置主优先级),子优先级是0-7,是2的3次方
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	//配置USART为中断源
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
	//配置抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	//配置子优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	//使能中断
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}
//串口初始化函数
void USART_Config(void){
	//1.初始化GPIO(PA9(接串口1的TX引脚),这里是PA10(接串口1的RX引脚))
	//初始化结构体 GPIO_InitStruct
	//里面是GPIO的速度,上下拉,输出类型等
	 GPIO_InitTypeDef   GPIO_InitStruct;
	//USART结构体
	 USART_InitTypeDef   USART_InitStruct;
	//打开GPIOA时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  //使能时钟必须放到前面,不然后面的操作不会使灯点亮
	//打开USART1时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
	//复位串口1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,  GPIO_AF_USART1); //PA9 复用为 USART1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //PA10 复用为 USART1
	//驱动是哪个引脚  PA9/PA10
	GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_9|GPIO_Pin_10;
	//模式是复用功能
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	//输出的速度
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	//推挽复用输出
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	//上拉
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	//变量获取它的指针,取地址就行(&)
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	//2.初始化串口
	//使能串口时钟 (放在最上面了)
	//配置波特率
	USART_InitStruct.USART_BaudRate = 115200;  //设置波特率115200
	//配置针数据字长
	USART_InitStruct.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
	//配置停止位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;     //设置为一个停止位
	//配置校验位
	USART_InitStruct.USART_Parity = USART_Parity_No;     //无奇偶校验位
	//配置硬件流控制
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不使用硬件流控制
	//配置工作模式
	USART_InitStruct.USART_Mode =  USART_Mode_Rx|USART_Mode_Tx;  //收发模式
	//完成串口的初始化配置
	USART_Init(USART1,&USART_InitStruct);
	//串口中断优先级配置(初始化)
	EXTI_NVIC_Config();
	//使能串口接收中断(中断配置函数)  这是使能哪种中断,比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  //生成串口中断   接收到数据就产生了中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);	// 开启空闲中断
	//使能串口(串口使能函数)
	USART_Cmd(USART1,ENABLE);
}

2.3 编写接收数据中断函数和空闲中断函数

空闲中断是在检测到在数据收后,总线上在一个字节的时间内没有再接收到数据时发生,所有在这个空闲中断函数里面判断接收的数据是led on还是led off。

  uint8_t rx_buff[50];  //声明一个数组,大小为51
  uint8_t rx_cnt = 0;   //数组索引为0
  uint8_t usart_idle_flag = 0; //没有在main函数里面写处理函数,所以没有用
  //接收数据中断函数
void USART1_IRQHandler(void){
	uint8_t i;  //打印接收的数据时用到
	unsigned int data;
	if(USART_GetITStatus(USART1,USART_IT_RXNE)){   //每当接收到1个字节,会产生USART_IT_RXNE中断              
		rx_buff[rx_cnt] = USART_ReceiveData(USART1);  //把这个数据放到数组中去
		rx_cnt++;
	}
	//空闲中断函数
	if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){ 
		data = USART1->SR;		 // 清空闲中断
		data = USART1->DR;        
		usart_idle_flag = 1;	// 产生空闲中断,没有用到
	//打印接收到的数据
	for(i=0;i<7;i++){
		printf("value = %x\n",rx_buff[i]);
	}		
	if(strcmp(rx_buff, "led on") == 0 ){      //判断两个字符串相等
		 GPIO_ResetBits(GPIOF,GPIO_Pin_10);   //置低位,LED灯亮
		 memset(rx_buff,0,sizeof(rx_buff));   //清空数组
		 rx_cnt = 0;                          //清空索引置为0
		} 
	if(strcmp(rx_buff, "led off") == 0){    //判断两个字符串相等
		 GPIO_SetBits(GPIOF,GPIO_Pin_10);   //置高位,LED灯灭
		 memset(rx_buff,0,sizeof(rx_buff)); //清空数组
		 rx_cnt = 0;                        //清空索引置为0
		}
	}
}

2.4 main.c函数

int main(void){
  LED_GPIO_Config();  //初始化LED
  USART_Config();     //初始化串口
  while(1){}
}

3. 实验结果

发送led on,灯亮,可以看到接收到的数据和发送的收据相同,0是因为数组里面没有那个数据。
在这里插入图片描述
在这里插入图片描述
发送led off,灯灭,可以看到接收到的数据和发送的数据相同。
在这里插入图片描述
在这里插入图片描述

4. 总结

在编写接收数据中断函数时,如果使用printf进行接收数据的打印时候,只会打印接收到的第一个字节。

	if(USART_GetITStatus(USART1,USART_IT_RXNE)){  //每当接收到1个字节,会产生USART_IT_RXNE中断             
		rx_buff[rx_cnt] = USART_ReceiveData(USART1);  //把这个数据放到数组中去
		//printf("value = %x\n",rx_buff[rx_cnt]);     //加上这只会接收到第一个字节
		//printf("value = %d\n",rx_cnt);
		rx_cnt++;
	}
  • 8
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要通过串口控制 LED ,您需要使用 CC2530 芯片来实现串口通信LED 控制。以下是基本的步骤: 1. 确保您已经连接了 CC2530 芯片和 LED 。 2. 创建一个新的工程,包括 CC2530 芯片和串口通信库。 3. 编写代码,实现串口通信LED 控制。您可以使用串口库来读取和发送数据。然后,根据收到的数据,您可以控制 LED 的状态。 4. 编译并上传代码到 CC2530 芯片上。 这里有一些示例代码,可以帮助您开始: ```c #include <ioCC2530.h> // 定义串口的波特率 #define BAUD_9600 0x0028 // 初始化串口 void uart_init() { PERCFG &= ~0x01; // 设置UART0在P0上 P0SEL |= 0x0C; // P0.2和P0.3设为外设 U0CSR |= 0x80; // UART模式 U0GCR |= 11; // 9600波特率 U0BAUD = BAUD_9600; U0CSR |= 0x40; // 允许接收 } // 发送一个字符到串口 void uart_send_char(char c) { while (!(U0CSR & 0x20)); // 等待发送缓冲区为空 U0DBUF = c; } // 发送一个字符串到串口 void uart_send_string(char* str) { while (*str != '\0') { uart_send_char(*str); str++; } } // 控制LED void control_led(int on) { if (on) { P1_0 = 1; } else { P1_0 = 0; } } void main() { uart_init(); while (1) { if (U0CSR & 0x01) { // 如果收到数据 char c = U0DBUF; if (c == '1') { // 打开LED control_led(1); uart_send_string("LED on!\r\n"); } else if (c == '0') { // 关闭LED control_led(0); uart_send_string("LED off!\r\n"); } } } } ``` 此代码将等待来自串口的数据。如果收到字符“1”,则打开 LED ,如果收到字符“0”,则关闭 LED 。它还会向串口发送消息以确认 LED 的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值