單片機與上位機通過串口通信

思路
(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爲 串口回顯
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章