項目基本實現和功能如下:
1、配置使用stm32 cubeMx
2、使用Ubuntu19環境、python3.7
3、實現電腦發送數據到單片機接收
4、單片機判斷接收的數據進行電燈流水燈等操作
5、單片機接收到的信息回傳給電腦,電腦顯示回傳的數據並顯示在終端
6、在實現過程中發現在改環境下兩個進程可以同時對串口數據進行讀寫,數據不會干擾太嚴重
電腦串口發送數據給單片機:
#!/usr/bin/python
#encoding:utf-8
import time
#import serial
import serial.tools.list_ports
plist = list(serial.tools.list_ports.comports()#使用此方法得到可用的usb口數據,把是串口的輸出成列表
if len(plist) <= 0: #如果輸出的列表是空的說明沒有打開任何串口
print("沒有發現端口!")
else:
plist_0 = list(plist[0])
serialName = plist_0[0]
#serialFd = serial.Serial(serialName, 9600, timeout=60)#串口基本的參數配置,配置完成後直接打開
print("可用端口名>>>", serialFd.name)
ser = serial.Serial(serialFd.name, 115200) # 設置了第一個串口號,波特率,讀超時等設置
while True:
ser.write('10\r\n'.encode())#向串口內寫入數據'10' 兩位數分別對應了單片機的兩個
time.sleep(0.2)#延時操作,程序順序等待0.2秒
ser.write('01\r\n'.encode())#1代表電量,0代表熄滅
time.sleep(0.2)
單片機回傳數據給電腦進行接收:
#!/usr/bin/python
#encoding:utf-8
import serial
import serial.tools.list_ports
"""查看可用串口操作"""
plist = list(serial.tools.list_ports.comports())
if len(plist) <= 0:
print("沒有發現端口!")
else:
plist_0 = list(plist[0])
serialName = plist_0[0]
#serialFd = serial.Serial(serialName, 9600, timeout=60)
print("可用端口名>>>", serialFd.name)
'''電腦接收數據'''
def recive_serial():
ser = serial.Serial(serialFd.name, 115200) # 設置了第一個串口號,波特率,讀超時設置
#ser.open()
while True:
#ser.write('10\r\n'.encode())
count = ser.inWaiting()#當沒有數據傳回電腦時,程序順序執行到此處進行等待
if count > 0:
recive = ser.read(count)#電腦讀取單片機回傳數據的方法
if recive == b'01\r\n':#沒有經過處理,直接硬駭識別
print("識別成功")
print(recive)
recive_serial()
上述兩個程序,在執行接收程序前需要先執行發送程序。發送程序回每隔0.2秒發送兩個對應碼錶的字符,分別是零和一,連個字符在單片機接收到後分別對應兩個燈進行閃爍操作。同時還會把數據回傳給電腦,接收程序此時纔會出現結果。
程序是在Ubuntu環境下編寫,在pycharm內正常運行編譯後卻無法在終端直接使用python編譯運行,找過之後才發現需要在.py文件最前面增加#!/usr/bin/python
這樣一句話
然而還會報錯,於是找資料,原理啊還需要這樣一句話:`#encoding:utf-8
#!/usr/bin/python是這樣解釋的:其中#!符號在計算機行業中叫做 “Shebang”, 其作用是指定由哪個解釋器來執行腳本。在這裏即是指定python作爲解釋器
#-- coding:utf-8 --:是爲了告訴Python解釋器,按照UTF-8編碼讀取源代碼,否則,你在源代碼中寫的中文輸出可能會有亂碼。
可以參考這篇博客:https://blog.csdn.net/qq1214052592/article/details/90046130
*分割線 2333333333333333333333333333333333333333333333 *
下面是單片機部分:
使用芯片stm32f103rct6 ,手上正好有原子的mini板子,於是使用新學的cubemx進行配置
如圖:只使用了這幾個簡單的引腳
上面的引腳均使用mini開發板上面的資源,使用外部晶振,串口一,使用兩個板子上面有的led的GPIO,其他的這沒有什麼了T_T
使用外部晶振的配置
分頻
串口1配置
配置完成,直接生成代碼,編譯,通過沒問題電燈沒問題
最後需要在main.c裏面增加下面的代碼
1、增加全局變量來保存串口相關數據
uint8_t aRxBuffer; //接收中斷緩衝
uint8_t Uart1_RxBuff[256]; //接收緩衝
uint8_t Uart1_Rx_Cnt = 0; //接收緩衝計數
uint8_t cAlmStr[] = "數據溢出(大於256)\r\n";
2、增加串口接收中斷函數,在主函數上面執行,初始化後面先執行
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
3、while(1)裏面的代碼
while (1)
{
/* USER CODE END WHILE */
if(Uart1_RxBuff[0] =='0') HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
else if(Uart1_RxBuff[0] =='1') HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
if(Uart1_RxBuff[1] =='0') HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
else if(Uart1_RxBuff[1] =='1') HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
/* USER CODE BEGIN 3 */
}
4、在主函數函數下面增加中斷服務函數
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
if(Uart1_Rx_Cnt >= 255) //溢出判斷
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收數據轉存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判斷結束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //將收到的信息發送出去
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空數組
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再開啓接收中斷
}
/* USER CODE END 4 */
完畢!!!
233333333!