单片机与上位机通过串口通信

思路
(1)引脚配置–PA9 (Tx) ----PA10 (Rx)
(2)串口配置 (数据协议:起始位–数据位–奇偶校验–停止位; 波特率)
(3)查看功能是否正常----回显函数 将下位机接收的数据发送到上位机(串口助手)显示

寄存器

//引脚配置   串口配置
void usart_config(u32 baud)//形参为波特率
{
	u32 div_m,div_f;//div_m--USARTDIV的整数部分  ---div_f  是小数部分  
	float usart_div;//    USARTDIV是什么?  这是波特率配置重点,我的笔记上次已经讲过
	RCC->APB2ENR |=(0X01<<2)|(0X01<<14);//开时钟  GPIOA   USART1
	//PA9--¸查看原理图 与英文数据手册 该管脚复用功能为USART1_Tx 故 应该配置  复用推挽输出  模式
	GPIOA->CRH &=~(0X0F<<4);
	GPIOA->CRH |=(0X0B<<4);
	//PA10--浮空或上拉输入模式
	GPIOA->CRH &=~(0X0F<<8);
	GPIOA->CRH |=(0X04<<8);
	//串口配置
	//配置字长--该位为0,则一个起始位,8个数据位 ;;该位为1,则一个起始位,9个数据位
	USART1->CR1 &=~(0x01<<12);
	//配置为0   不使用奇偶校验
	USART1->CR1 &=~(0x01<<10);
	//使能串口的发送与接收
	USART1->CR1 |=(0x01<<3)|(0x01<<2);
	//配置停止位   00:1个停止位;;  01:0.5个停止位;; 10:2个停止位;; 11:1.5个停止位;
	USART1->CR2 &=~(0x03<<12);
	//波特率配置
	usart_div=72000000.0/(16*baud);
	//整数部分
	div_m=(u32)usart_div;
	//小数部分
	div_f=(u32)((usart_div-div_m)*16);
	//USART_BRR寄存器   0-3 存储USARTDIV 的小数部分   4-15保存USARTDIV的整数部分
	USART1->BRR =div_m<<4|div_f;
	//最重要是一步  配置完成一定要使能USART
	USART1->CR1 |=(0x01<<13);
}
//回显函数
void echo_usart(void)
{
	u8 data;
	//USART的状态寄存器  等待接收数据
	while((USART1->SR &(0x01<<5))==0);
	//如果收到数据   就把数据赋值给data变量
	//USART_DR   数据寄存器   保存发送或接受的数据
	data=USART1->DR;
	//等待数据转移到移位寄存器    
	while((USART1->SR &(0x01<<7))==0);
	//将之前接收的数据放入寄存器等待发出
	USART1->DR=data;
}
//打印函数  将数据显示到上位机(串助手上)
int fputc(int c, FILE * stream)
{
	while(((USART1->SR) &(0x01<<7))==0);
	USART1->DR=(u8)c;
	return c;
}

库函数

void usart_init (void)
{
	//定义结构体
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	//开时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  
  //GPIO配置  PA9   复用推挽
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  //初始化
  GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIO配置  PA10   寄存器版是浮空输入   这里配置上拉输入模式  效果都一样
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  //初始化
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  //串口配置
  USART_InitStructure.USART_BaudRate = 9600;//波特率
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8字节
  USART_InitStructure.USART_Parity = USART_Parity_No;//不使用奇偶校验
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//输入输出使能
  //初始化
  USART_Init(USART1, &USART_InitStructure);
  //使能USART1
  USART_Cmd(USART1, ENABLE);//ʹÄÜ
}
//回显函数
void echo_usart(void)
{
	u8 val=0xff;
	// 检查指定的USART标志    USART_FLAG_RXNE :接收数据寄存器不为空标志
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
	//将数据传给val
	val=USART_ReceiveData(USART1);
	//将收到是数据发出
	USART_SendData(USART1,val);
}
//打印函数
int fputc(int ch, FILE *f)
{
  // 检查指定的USART标志    USART_FLAG_RXNE :接收数据寄存器不为空标志
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  USART_SendData(USART1, (uint8_t) ch);
  return ch;
}

结果显示 123456为主函数 printf输出 666为 串口回显
单片机与上位机通过串口通信_第1张图片

你可能感兴趣的:(STM32开发)