嵌入式STM32课程实验-串口实验

外接CH340,在电脑端安装好CH340驱动,连接电脑,通过电脑的串口助手发送学号点亮对应LED灯,发送姓名熄灭LED灯。

接收函数、比较函数要求自己撰写。(不然可以通过调用strcmp函数即可)

1、main.c部分:

#include "stm32f10x.h"                  // Device header
#include <string.h>
#include "Delay.h"
#include "LED.h"
#include "Serial.h"

char * xuehao = "202078057912";
char * name = "张三";

int main(void)
{
	LED_Init();

	LED2_OFF();
	
	Serial_Init();
	send_string("Hello\r\n");

	while(1)                       
	{	
		
		if (Compare_arrays_to_strings(recv_data_buff, xuehao) == 1)//判断两个字符串是否相等(如果相等会返回0)
		{
			LED1_ON();
		}
		if (Compare_arrays_to_strings(recv_data_buff, name) == 1)//判断两个字符串是否相等(如果相等会返回0)
		{
			LED1_OFF();
		}
	}
}

2、Serial.c部分

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
#include "led.h"

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);		//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//开启时钟

	//初始化GPIOA引脚
	GPIO_InitTypeDef GPIO_InitStructure;                    	//定义一个结构体变量
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        		//GPIO模式:复用推挽输出(供USART的TX使用)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  					//用到GPIO9号口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       	//GPIO的速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);     		        	//初始化GPIOA外设,结构体变量名取地址(地址传递)
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;       		//GPIO模式:浮空输入模式(供USART的RX使用)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  				//用到GPIO10号口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       	//GPIO的速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);     		        	//初始化GPIOA外设,结构体变量名取地址(地址传递)
	//一般RX配置是浮空输入或上拉输入,因为串口波形空闲状态是高电平,所以不使用下拉输入
	
	//配置USART初始化
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;										//波特率(Init函数内部会自动算好9600对应的分频系数,然后写入BRR寄存器)
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制(不使用流控)
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;					//串口模式(发送和接受)
	USART_InitStructure.USART_Parity = USART_Parity_No;								//校验位(无校验)
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							//停止位(一位停止位)
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//字长(8位)
	USART_Init(USART1, &USART_InitStructure);
	//对于串口接收来说,可以使用查询和中断两种方法,如果使用查询,初始化到这里就可以了
	
	//用中断的方法(需要开启中断)
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);			//开启RXNE标志位到NVIC的输出(RXNE标志位一但置1,就会向NVIC申请中断)
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//分组
	
	//初始化NVIC的USART1的通道
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		//中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init( &NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}


void Send_Byte(uint8_t res)
{
	USART_SendData(USART1,res);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == 0);
}

void send_string(char * data)
{
	uint8_t i = 0;
	while(data[i] != '\0')
	{
		Send_Byte(data[i]);
		i ++;
	}
}

uint8_t sta_rea_flag,sta_flag;
uint8_t end_rea_flag,end_flag;
char recv_data_buff[50];
uint16_t recv_data_point;

void USART1_IRQHandler(void)
{
	uint8_t res = 0;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判断标志位
	{
		res = USART_ReceiveData(USART1);
		if (sta_flag != 1)						//判断包头
		{
			if (sta_rea_flag == 1)
			{
				if (res == 0xff)
				{
					sta_flag = 1;
					for(int i = 0;i < recv_data_point; i ++)
						recv_data_buff[i] = 0;
					recv_data_point = 0;

				}
				else
					sta_rea_flag = 0;
			}
			else if (res == 0xff)
				sta_rea_flag = 1;
		}
		else
		{
			if (end_flag != 1)						//判断包尾
			{
				if (end_rea_flag == 1)
				{
					if (res == '\n')
					{
						end_flag = 0;
						end_rea_flag = 0;
						sta_flag = 0;
						sta_rea_flag = 0;

					}
					else
						end_rea_flag = 0;
				}
				else if (res == '\r')
					end_rea_flag = 1;
				else
				{
					recv_data_buff [recv_data_point] = res;
					recv_data_point ++;			

				}
			}
		}
		//是否要手动清除标志位要参考手册,这里如果读取了DR就可以自动清除,没读取就要手动
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

int16_t Compare_arrays_to_strings(char *a,char *b)
{
	int i = 0;
	if(a[i] != 0)
	{
		do
		{
			if( a[i] == *(b+i))
			{
				i++;
			}	
			else if( a[i] != *(b+i))
				return 0;
			if((a[i] == 0) && (b[i] != 0))
				return 0;
			if((a[i] != 0) && (b[i] == 0))
				return 0;
		}while((a[i] != 0) && (b[i] != 0));
		return 1;
	}
	return 0;
}

3、LED.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void LED_Init(void)										    //LED初始化函数
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);   //APB2外设时钟控制(接在GPIOA上,使能)
	
	GPIO_InitTypeDef GPIO_InitStructure;                    //定义一个结构体变量
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //GPIO模式:推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;  //用到GPIO1、2号口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //GPIO的速度
	GPIO_Init(GPIOG,&GPIO_InitStructure);     		        //初始化GPIOA外设,结构体变量名取地址(地址传递)
	
	GPIO_SetBits(GPIOG, GPIO_Pin_6 | GPIO_Pin_8);           //GPIOA 1、2口设置为高电平
}

void LED1_ON(void)
{
	GPIO_ResetBits(GPIOG,GPIO_Pin_6);
}

void LED1_OFF(void)
{
	GPIO_SetBits(GPIOG,GPIO_Pin_6);
}

void LED1_Turn(void)
{
	if(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6)==0)         //读取现在的输出值
	{
		GPIO_SetBits(GPIOG, GPIO_Pin_6);
	}
	else
	{
		GPIO_ResetBits(GPIOG,GPIO_Pin_6);
	}
	Delay_ms(10);
}

void LED2_ON(void)
{
	GPIO_ResetBits(GPIOG,GPIO_Pin_8);
}

void LED2_OFF(void)
{
	GPIO_SetBits(GPIOG,GPIO_Pin_8);
}

void LED2_Turn(void)
{
	if(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_8)==0)
	{
		GPIO_SetBits(GPIOG, GPIO_Pin_8);
	}
	else
	{
		GPIO_ResetBits(GPIOG,GPIO_Pin_8);
	}
}

其他.h文件自己创建即可,或者都放在main.c文件里也可以,不需要其他文件。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慢慢丶丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值