项目基本实现和功能如下:
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!