stm32F103 RS232通信实验
- 什么是RS232?
- 软件设计
- 完整工程下载
这里注意使用的是负逻辑电平信号,在规定范围内的电平信号代表逻辑1或0,增加了抗干扰能力。
(电平的转化由硬件设计,TTL信号转232信号,常用的芯片有ST3232ECTR,MAX3232)
RS232能够弥补串口的一些不足,像传输距离,抗干扰能力,等都有提高。
RS232存在的不足,于是就有了RS485(下一篇讲解)
这里和UART通信不同的是所用到的引脚不同,所以在编程配置的时候只需要在原来的基础上更改对应引脚。
点击查看UART通信实验RS232实验功能与UART所实现功能一致
本实验需要USB转RS232线(公母头根据自己的开发板选择)
UART.C
#include"stm32f10x_exti.h"
#include"stm32f10x_gpio.h"
#include "usart.h"
void USART1_Init(unsigned long ulBaud)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//引脚时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//串口时钟
//配置USART1 TX引脚工作模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置USART1 RX引脚工作模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//串口1工作模式配置
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ClearFlag(USART1,USART_FLAG_TC);//清除发送完成标志
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启USART1接收中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART2_Init(unsigned long ulBaud)
{
GPIO_InitTypeDef GPIO_InitStruct;//定义结构体(GPIO,USART,NVIC)
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 允许GPIOA和USART2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// PA2-TX2复用推挽输出(端口配置)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* PA3-TX2浮空输入(复位状态,可以省略)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct); */
// 初始化USART2(波特率ulBaud,允许Rx和Tx,默认8个数据位,1个停止位,无校验)
USART_InitStruct.USART_BaudRate = ulBaud;//波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位
USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位
USART_InitStruct.USART_Parity = USART_Parity_No;//(校验位:无)
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置收发模式
USART_InitStruct.USART_HardwareFlowControl= USART_HardwareFlowControl_None;//硬件流控制:无
USART_Init(USART2, &USART_InitStruct);//串口2初始化
USART_Cmd(USART2, ENABLE);//使能USART2
USART_ClearFlag(USART2,USART_FLAG_TC);//清除发送完成标志
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启USART2接受中断
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//主优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStruct);//中断初始化
}
// 发送字符
unsigned char USART_SendChar(USART_TypeDef* USARTx, unsigned char ucChar)
{
while(!USART_GetFlagStatus(USARTx, USART_FLAG_TXE));
USART_SendData(USARTx, ucChar);
return ucChar;
}
// 发送字符串
void USART_SendString(USART_TypeDef* USARTx, unsigned char* pucStr)
{
while(*pucStr != '\0')
USART_SendChar(USARTx, *pucStr++);
}
// 非阻塞接收字符
unsigned char USART_ReceiveChar_NonBlocking(USART_TypeDef* USARTx)
{
if(USART_GetFlagStatus(USARTx, USART_FLAG_RXNE))
return USART_ReceiveData(USARTx);
else
return 0;
}
#define uart1 //注释掉该宏使用uart2
#ifdef uart1
//printf调用函数(使用MicroLIB)
int fputc(int ch, FILE *f)
{
return(USART_SendChar(USART1, ch));
}
#else
// printf调用函数(使用MicroLIB)
int fputc(int ch, FILE *f)
{
return(USART_SendChar(USART2, ch));
}
#endif
}
main.c
#include "key.h"
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "usart.h"
#include "stm32f10x_exti.h"
void LCD_Proc(void);
void LED_Proc(void);
void Key_Init(void);
void LED_Control(uint16_t LED,uint8_t LED_Status);
void USART1_Init(unsigned long ulBaud);
uint32_t TimingDelay = 1;
unsigned char ucSec,ucLed=1;
unsigned long ulTick_ms;
int col_flag=0;
unsigned int i;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
Key_Init();
LED_Init();
BUZ_Init();
STM3210B_LCD_Init(); //LCD的初始化
LCD_Clear(Cyan); //清屏配置颜色
LCD_SetTextColor(White); //字体颜色
LCD_SetBackColor(Cyan); //字体背景颜色
LED_Control(LEDALL,0);//控制所有LED灯默认关闭(0关闭,1打开)
USART1_Init(9600);
USART_SendString(USART1,"请输入您的指令:\r\n");
USART_SendString(USART1," 输入0:LED左移\r\n");
USART_SendString(USART1," 输入1:LED右移\r\n");
USART_SendString(USART1," 输入2:打开蜂鸣器\r\n");
USART_SendString(USART1," 输入3:关闭蜂鸣器\r\n\r\n");
while(1)
{
LCD_Proc();
LED_Proc();
}
}
void LED_Proc(void)
{
switch(col_flag)
{
case 1:
if(ulTick_ms > 300) //0.3S延时
{
ulTick_ms = 0;
ucLed >>= 1;
if(ucLed == 0)
ucLed =0x80; //LED右移函数
LED_Disp(ucLed);
}
break;
case 2:
if(ulTick_ms > 300) //0.3S延时
{
ulTick_ms = 0;
LED_Disp(ucLed);
ucLed <<= 1; //LED左移函数
if(ucLed ==0)
ucLed = 1;
}
break;
case 3:
LED_Control(LEDALL,0);
GPIO_ResetBits(GPIOB,GPIO_Pin_4);//打开蜂鸣器
break;
case 4:
LED_Control(LEDALL,0);
GPIO_SetBits(GPIOB,GPIO_Pin_4);
}
}
/*************************************
LCD中文显示需要做字库,在fonts.h文件内
*************************************/
//LCD中文显示
void LCD_Proc(void)
{
LCD_DisplayStringLine(Line1," 19");
LCD_DisplayproHZ(Line1, 4, 0);
LCD_DisplayproHZ(Line1, 5, 1);
LCD_DisplayproHZ(Line1, 6, 2); //嵌入式
if(col_flag==1)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line3," 1. LED");
LCD_DisplayproHZ(Line3, 5, 4);
LCD_DisplayproHZ(Line3, 6, 5); //右移
LCD_SetBackColor(Cyan);
if(col_flag==2)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line5," 2. LED");
LCD_DisplayproHZ(Line5, 5, 3);
LCD_DisplayproHZ(Line5, 6, 5); //左移
LCD_SetBackColor(Cyan);
if(col_flag==3)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line7," 3.");
LCD_DisplayproHZ(Line7, 3, 6);
LCD_DisplayproHZ(Line7, 4, 7);
LCD_DisplayproHZ(Line7, 5, 8);
LCD_DisplayproHZ(Line7, 6, 9); //蜂鸣器开
LCD_SetBackColor(Cyan);
if(col_flag==4)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line9," 4.");
LCD_DisplayproHZ(Line9, 3, 6);
LCD_DisplayproHZ(Line9, 4, 7);
LCD_DisplayproHZ(Line9, 5, 8);
LCD_DisplayproHZ(Line9, 6, 10); //蜂鸣器关
LCD_SetBackColor(Cyan);
}
//按键中断
void Key_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;//定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//时钟配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* PA0和PA8浮空输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0|GPIO_PinSource8);
/* PB1和PB2浮空输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1|GPIO_PinSource2);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//打开PA0中断连接
EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);//打开PA8中断连接
EXTI_ClearITPendingBit(EXTI_Line8);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//打开PB1中断连接
EXTI_ClearITPendingBit(EXTI_Line1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);//打开PB2中断连接
EXTI_ClearITPendingBit(EXTI_Line2);
EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line8|EXTI_Line1|EXTI_Line2;//选择中断线0,8,2,1
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//设置中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能中断线
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
//PA0
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
//PA8
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// PB1
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// PB2
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//中断服务函数
void EXTI0_IRQHandler(void) //PA0
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line0)!=RESET)
{
EXTI_ClearFlag(EXTI_Line0);
col_flag++;
if(col_flag>4)
col_flag=1;
}
}
void EXTI9_5_IRQHandler(void) //PA8
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line8)!=RESET)
{
EXTI_ClearFlag(EXTI_Line8);
col_flag--;
if(col_flag<1)
col_flag=4;
}
}
void EXTI1_IRQHandler(void) //PB1
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line1)!=RESET)
{
EXTI_ClearFlag(EXTI_Line1);
col_flag++;
if(col_flag>4)
col_flag=1;
}
}
void EXTI2_IRQHandler(void) //PB2
{ for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line2)!=RESET)
{
EXTI_ClearFlag(EXTI_Line2);
col_flag--;
if(col_flag<1)
col_flag=4;
}
}
//串口中断服务函数
void USART1_IRQHandler(void)
{
uint8_t temp;
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=0)
{
temp=USART_ReceiveData(USART1);
USART_SendData(USART1,temp);
switch(temp)
{
case'0':
col_flag=1;
USART_SendString(USART1,":LED右移已打开\r\n\r\n");
break;
case'1':
col_flag = 2;
USART_SendString(USART1,":LED左移已打开\r\n\r\n");
break;
case'2':
//col_flag = 3; //太吵了,实验自己打开
USART_SendString(USART1,":蜂鸣器已打开\r\n\r\n");
break;
case'3':
col_flag = 4;
USART_SendString(USART1,":蜂鸣器已关闭\r\n\r\n");
break;
}
}
}
void SysTick_Handler(void)
{
ulTick_ms++;
if(ulTick_ms%1000 == 0) ucSec+=0;
}
选择第12个工程