stm32串口使用:
1、printf函數調用
IAR的option設置中將printf庫打開再編寫printf重定向到usartn的函數
int fputc(int ch, FILE *f)
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until transmit data register is empty */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
使用usb轉TTL直接連接MCU與計算機即可。
除TTL外,rs232與rs485都可作爲串口線使用。
使用區別在於232餘485電平不同
接線不同rs232三線制 TX、RX、GND 全雙工通信,rs485兩線制 ,485+、485- 半雙工通信(接法不同也可全雙工通信,資料所說,沒調試過)
通信協議,rs232點對點通信,rs485總線形式通信。
傳輸距離不同,rs485可傳輸幾十米到上千米,rs232有效傳輸距離爲15米。
使用接線與芯片不同,mcu使用232芯片,即使用232串口線,使用485芯片即使用485串口線。
2、串口收發
串口接收:
關鍵點:初始化中的1、波特率 2、使能接收中斷 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 其餘初始化按部就班
static void Bsp_UsartInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
/* Configure pins as AF pushpull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1,ENABLE);
/* USART1 IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
串口讀取函數,該函數兼容一個MCU多個串口根據定義的串口號來調用同個函數,使用讀寫wp rp 位置指針存取讀取數據
uint8 Sys_ComReadByte(uint8 ComNum, uint8 *pData,uint8 len)
{
if(ComNum >= SYS_COM_NUM) //多個串口使用
{
return FALSE;
}
if(g_Data.ComInfo.DevToApp[ComNum].rp == g_Data.ComInfo.DevToApp[ComNum].wp)
{
return FALSE;
}
for(int i=0;i<len;i++)
{
*pData++ = g_Data.ComInfo.DevToApp[ComNum].Data[g_Data.ComInfo.DevToApp[ComNum].rp];
g_Data.ComInfo.DevToApp[ComNum].rp = (g_Data.ComInfo.DevToApp[ComNum].rp+1)%SYS_COM_BUF_SIZE;
}
return TRUE;
}
中斷函數中接收數據
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
/* Read one byte from the receive data register */
g_Data.ComInfo.DevToApp[BSP_485_COM].Data[g_Data.ComInfo.DevToApp[BSP_485_COM].wp] = (USART_ReceiveData(USART1) & 0x7F);
g_Data.ComInfo.DevToApp[BSP_485_COM].wp = (g_Data.ComInfo.DevToApp[BSP_485_COM].wp+1)%SYS_COM_BUF_SIZE;
}
串口發送:
使用串口發送中斷,中斷分爲兩種一種爲USART_IT_TC第二種爲USART_IT_TXE
使用過程中碰到一個問題是,當串口初始化完之後,使能了USART_IT_TC中斷,並且打開了總中斷後程序一直進入中斷,跳不出來。
後查詢原因解釋說,TC中斷全稱爲transmission complete,發送完中斷,在初始化使能中斷後會自動發送一個空閒幀。我試過在使能中斷之前或者之後或者在中斷函數裏都 單獨進行清TC標誌位,但退不出中斷。後改使用TXE中斷
TXE中斷即爲TX DR EMPTY 發送寄存器爲空就產生中斷,所以使用過程中的順序爲,初始化時不使能中斷,在調用發送函數後,或使用寄存器操作時當該寄存器不爲空時使能 該中斷USART_IT_TXE,然後在串口中斷裏當接收完所有數據後失能該中斷,以保證不會重複進入中斷。
串口寫入數據函數:該函數兼容一個MCU多個串口使用,使用定義串口號來使用,並使用讀寫rp與wp位置指針
uint16 Sys_ComWrite(uint8 ComNum, uint8 *pData, uint16 SLen)
{
if(ComNum >= SYS_COM_NUM)
{
return FALSE;
}
if(SLen==0)
{
return FALSE;
}
Bsp_SetDealyMs(SYS_COM_SEND_DELAY_TIME);
while(1)/* 等待緩衝區的數據全部發送完成 */
{
if((g_Data.ComInfo.AppToDev[ComNum].rp==0)
&&(g_Data.ComInfo.AppToDev[ComNum].wp==0))
{
break;
}
if(!Bsp_GetDealyMs())
{
break;
}
}
memcpy(g_Data.ComInfo.AppToDev[ComNum].Data, pData, SLen);
g_Data.ComInfo.AppToDev[ComNum].rp = 1;
g_Data.ComInfo.AppToDev[ComNum].wp = SLen;
switch(ComNum)
{
case 0:
break;
case 1:
USART_SendData(USART1, g_Data.ComInfo.AppToDev[ComNum].Data[0]);
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 發送寄存器爲空產生中斷,固要在發送函數後打開中斷使能,中斷接收完數據後失能
break;
case 2:
break;
default:
break;
}
Bsp_SetDealyMs(0);
return SLen;
}
接收中斷內容
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
/* Write one byte to the transmit data register */
if(g_Data.ComInfo.AppToDev[BSP_485_COM].wp > g_Data.ComInfo.AppToDev[BSP_485_COM].rp)
{
USART_SendData(USART1, g_Data.ComInfo.AppToDev[BSP_485_COM].Data[g_Data.ComInfo.AppToDev[BSP_485_COM].rp]);
g_Data.ComInfo.AppToDev[BSP_485_COM].rp = (g_Data.ComInfo.AppToDev[BSP_485_COM].rp+1)%SYS_COM_BUF_SIZE;
}
else
{
g_Data.ComInfo.AppToDev[BSP_485_COM].wp = 0;
g_Data.ComInfo.AppToDev[BSP_485_COM].rp = 0;
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); \\接收完數據後失能中斷
}
}
以上內容爲個人使用過程的方法筆記及個人認爲的注意點、知識點,內容不全面,如之後使用有所補充隨時更新。如您發現有所問題,希望給我意見。