【实验目的】
深入理解串口协议和串口程序编制方法;
【实验要求】
1.学会编写串口通信程序
2.能够使用按键控制通信消息的发送
2.学会在两块开发板之间通信的方式
【实验内容】
1.将开发板和PC机串口连接,并通过串口线和另一块开发板连接;
2.在发送开发板上按下发送键,则向目标开发板发送一个字符串;
3.目标开发板通过另一个串口将接收到的字符串发串口助手显示;
【实验过程】
1.硬件连接
*使用战舰开发板完成实验
使用USART1的USB串口与PC完成连接,使用USART2通过杜邦线与另一块开发板的USART2跳线处完成连接。
图1 硬件连接(仅显示数据线连接,需共地线)
2.接口技术
USART:通用同步异步串口,通信方式为全双工通信方式,可同时接发数据。其中开发板的USART1与CH340转串口芯片连接,将USART TTL转化为USB通信与PC机相连。USART通过RX,TX,GND与另一块开发板相连。
2.程序逻辑
在与PC机相连的开发板上,通过将USART2接受到的数据反馈到USART1中,通过串口助手可以查看数据,方便调试。
在未与PC相连的开发板中,按下独立按键Key1后,串口USART2发送数据,另一块开发板收到信息后,点亮开发板LED灯,并向USART1发送数据。
3.程序展示
(1)按键及LED初始化【使用位带操作】
LED_KEY_Init
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
- //初始化 WK_UP-->GPIOA.0 下拉输入
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
- GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
- GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
- GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
- //初始化 WK_UP-->GPIOA.0 下拉输入
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
Led_Key
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO口地址映射
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
- #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
- #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
- #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
- #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
- #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
- #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
- #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
- //IO口操作,只对单一的IO口!
- //确保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
头文件声明
- #define LED0 PBout(5)
- #define LED1 PEout(5)
- #define Key0 PEin(4)
- #define Key1 PEin(3)
- #define Key2 PEin(2)
按键中断
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能复用功能时钟
- EXTI_InitTypeDef EXTI_InitStructure;
- EXTI_InitStructure.EXTI_Line = EXTI_Line0;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
- EXTI_Init(&EXTI_InitStructure); // 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 使能按键WK_UP所在的外部中断通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级2,
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; // 子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能外部中断通道
- NVIC_Init(&NVIC_InitStructure);
- NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; // 使能按键KEY2所在的外部中断通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级2,
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; // 子优先级2
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能外部中断通道
(2)串口初始化
- void Serial_Init()
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
- GPIO_InitTypeDef g;
- g.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- g.GPIO_Pin = GPIO_Pin_3;
- g.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &g);
- g.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- g.GPIO_Pin =GPIO_Pin_10;
- g.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&g);
- g.GPIO_Mode =GPIO_Mode_AF_PP;
- g.GPIO_Pin = GPIO_Pin_2;
- g.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &g);
- g.GPIO_Mode = GPIO_Mode_AF_PP;
- g.GPIO_Pin =GPIO_Pin_9;
- g.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&g);
- USART_InitTypeDef u;
- u.USART_BaudRate = 9600;
- u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- u.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- u.USART_Parity = USART_Parity_No;
- u.USART_StopBits = USART_StopBits_1;
- u.USART_WordLength = USART_WordLength_8b;
- USART_Init(USART2, &u);
- USART_Init(USART1, &u);
- NVIC_InitTypeDef n;
- n.NVIC_IRQChannel = USART2_IRQn;
- n.NVIC_IRQChannelCmd = ENABLE;
- n.NVIC_IRQChannelPreemptionPriority = 1;
- n.NVIC_IRQChannelSubPriority = 2;
- NVIC_Init(&n);
- n.NVIC_IRQChannel = USART1_IRQn;
- n.NVIC_IRQChannelCmd = ENABLE;
- n.NVIC_IRQChannelPreemptionPriority = 1;
- n.NVIC_IRQChannelSubPriority = 1;
- NVIC_Init(&n);
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
- USART_Cmd(USART1,ENABLE);
- USART_Cmd(USART2,ENABLE);
- }
(3)中断操作配置
- void USART2_IRQHandler()
- {
- if(USART_GetITStatus(USART2, USART_IT_RXNE) == 1)
- {
- usart2_read[p++]= USART_ReceiveData(USART2);
- USART_ClearITPendingBit(USART2, USART_IT_RXNE);
- }
- }
- void USART1_IRQHandler()
- {
- if(USART_GetITStatus(USART1, USART_IT_RXNE) == 1)
- {
- usart1_read[q++]= USART_ReceiveData(USART1);
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);
- }
- }
- // 外部中断2服务程序
- void EXTI2_IRQHandler(void)
- {
- Delay_ms(10); // 消抖
- if (Key2 == 0) // 按键KEY2
- {
- USART2_send();
- LED0=0;
- }
- EXTI_ClearITPendingBit(EXTI_Line2); // 清除LINE2上的中断标志位
- }
(4)逻辑操作_按键跳转函数
- void USART2_send()
- {
- uint8_t i=0;
- for(i=0;i<8;i++)
- {
- while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)!= 1 );
- USART_SendData(USART2,cmd1[i]);
- }
- }
Main
- while(1)
- {
- if(p==7);
- {
- p=0;
- for(i=0;i<8;i++)
- {
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)!= 1 );
- USART_SendData(USART1,usart2_read[i]);
- }
- }
- }
4.效果展示
标签:NVIC,Addr,USART,通信,stm32,InitStructure,串口,GPIO,define From: https://blog.csdn.net/hilws760/article/details/142257953