超詳細(xì)OpenMV與STM32單片機(jī)通信 附完整源碼
1.前言(閑話)
最近在做電磁炮,發(fā)現(xiàn)題目需要用到顏色跟蹤,于是花了一點(diǎn)時(shí)間學(xué)了一下OpenMV,只學(xué)習(xí)OpenMV是遠(yuǎn)遠(yuǎn)不夠的,還需要實(shí)現(xiàn)與單片機(jī)的通信,本以為很簡單,在CSDN上找了一些代碼,直接拿來修改粘貼,把代碼看明白了,這些只花了幾個(gè)小時(shí),本以為自己已經(jīng)弄明白了二者之間的通信,但是在后期把OpenMV端數(shù)據(jù)傳輸?shù)絾纹瑱C(jī)的時(shí)候卻犯了難。我選擇使用OLED顯示傳輸?shù)臄?shù)據(jù),在這里調(diào)試了許久,中間遇到了許多之前的學(xué)習(xí)漏洞,特在此寫下博客記錄學(xué)習(xí)經(jīng)歷。*
2.硬件連接
我所用到的材料如下: 四針I(yè)IC OLED,OpenMV(OV7725),STM32F103C8T6最小系統(tǒng)板,數(shù)據(jù)線N條(OpenMV的數(shù)據(jù)線只能用官方自帶的,其他的基本都用不了),杜邦線若干。
1.OpenMV端:由圖知UART_RX—P5 ------ UART_TX—P4

2.STM32端:USART_TX—PA9 -----USART_RX—PA10

3.四針OLED IIC連接:SDA—PA2-----SCL—PA1 由于使用的是模擬IIC而不是硬件IIC,可以根據(jù)個(gè)人需要修改IO口來控制SDA線和SCL線,只需要簡單修改一下代碼即可。
4.STM32的TX(RX)接OpenMV的RX(TX),OLED連接到STM32即可。
3.軟件代碼———OpenMV端
import sensor, image, time,math,pyb
from pyb import UART,LED
import json
import ustruct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
red_threshold_01=(10, 100, 127, 32, -43, 67)
clock = time.clock()
uart = UART(3,115200) #定義串口3變量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
def find_max(blobs): #定義尋找色塊面積最大的函數(shù)
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
def sending_data(cx,cy,cw,ch):
global uart;
#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
#data = bytearray(frame)
data = ustruct.pack("<bbhhhhb", #格式為倆個(gè)字符倆個(gè)短整型(2字節(jié))
0x2C, #幀頭1
0x12, #幀頭2
int(cx), # up sample by 4 #數(shù)據(jù)1
int(cy), # up sample by 4 #數(shù)據(jù)2
int(cw), # up sample by 4 #數(shù)據(jù)1
int(ch), # up sample by 4 #數(shù)據(jù)2
0x5B)
uart.write(data); #必須要傳入一個(gè)字節(jié)數(shù)組
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold_01])
cx=0;cy=0;
if blobs:
max_b = find_max(blobs)
#如果找到了目標(biāo)顏色
cx=max_b[5]
cy=max_b[6]
cw=max_b[2]
ch=max_b[3]
img.draw_rectangle(max_b[0:4]) # rect
img.draw_cross(max_b[5], max_b[6]) # cx, cy
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
#sending_data(cx,cy,cw,ch)
uart.write(FH)
print(cx,cy,cw,ch)
bytearray([, , ,])組合uart.write()的作用與直接調(diào)用sending_data(cx,cy,cw,ch)作用是一樣的
4.軟件代碼———STM32端
工程總共包含如下文件:main.c、iic.c、iic.h、oled.c、oled.h、uart.c、uart.h。由于OLED的代碼存在版權(quán)問題,需要的可以郵箱私發(fā)。
/***** oled.h *****/
#ifndef __USART_H #define __USART_H #include "sys.h" void USART1_Init(void);//串口1初始化并啟動 #endif
/***** oled.c *****/
#include "uart.h"
#include "oled.h"
#include "stdio.h"
static u8 Cx=0,Cy=0,Cw=0,Ch=0;
void USART1_Init(void)
{
//USART1_TX:PA 9
//USART1_RX:PA10
GPIO_InitTypeDef GPIO_InitStructure; //串口端口配置結(jié)構(gòu)體變量
USART_InitTypeDef USART_InitStructure; //串口參數(shù)配置結(jié)構(gòu)體變量
NVIC_InitTypeDef NVIC_InitStructure; //串口中斷配置結(jié)構(gòu)體變量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打開PA端口時(shí)鐘
//USART1_TX PA9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設(shè)定IO口的輸出速度為50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//USART1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ; //搶占優(yōu)先級0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子優(yōu)先級2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = 115200; //串口波特率為115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能中斷
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC); //清串口1發(fā)送標(biāo)志
}
//USART1 全局中斷服務(wù)函數(shù)
void USART1_IRQHandler(void)
{
u8 com_data;
u8 i;
static u8 RxCounter1=0;
static u16 RxBuffer1[10]={0};
static u8 RxState = 0;
static u8 RxFlag1 = 0;
if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) //接收中斷
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中斷標(biāo)志
com_data = USART_ReceiveData(USART1);
if(RxState==0&&com_data==0x2C) //0x2c幀頭
{
RxState=1;
RxBuffer1[RxCounter1++]=com_data;OLED_Refresh();
}
else if(RxState==1&&com_data==0x12) //0x12幀頭
{
RxState=2;
RxBuffer1[RxCounter1++]=com_data;
}
else if(RxState==2)
{
RxBuffer1[RxCounter1++]=com_data;
if(RxCounter1>=10||com_data == 0x5B) //RxBuffer1接受滿了,接收數(shù)據(jù)結(jié)束
{
RxState=3;
RxFlag1=1;
Cx=RxBuffer1[RxCounter1-5];
Cy=RxBuffer1[RxCounter1-4];
Cw=RxBuffer1[RxCounter1-3];
Ch=RxBuffer1[RxCounter1-2];
}
}
else if(RxState==3) //檢測是否接受到結(jié)束標(biāo)志
{
if(RxBuffer1[RxCounter1-1] == 0x5B)
{
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);//關(guān)閉DTSABLE中斷
if(RxFlag1)
{
OLED_Refresh();
OLED_ShowNum(0, 0,Cx,3,16,1);
OLED_ShowNum(0,17,Cy,3,16,1);
OLED_ShowNum(0,33,Cw,3,16,1);
OLED_ShowNum(0,49,Ch,3,16,1);
}
RxFlag1 = 0;
RxCounter1 = 0;
RxState = 0;
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
}
else //接收錯誤
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00; //將存放數(shù)據(jù)數(shù)組清零
}
}
}
else //接收異常
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00; //將存放數(shù)據(jù)數(shù)組清零
}
}
}
}
解釋:OpenMV發(fā)送數(shù)據(jù)包給STM32,STM32利用中斷接收數(shù)據(jù)并把數(shù)據(jù)存放在RxBuffer1這個(gè)數(shù)組里,并且在中斷中利用OLED顯示cx,cy,cw,ch四個(gè)坐標(biāo)。在中斷中,有如下函數(shù):
else if(RxState==2)
{
RxBuffer1[RxCounter1++]=com_data;
if(RxCounter1>=10||com_data == 0x5B) //RxBuffer1接受滿了,接收數(shù)據(jù)結(jié)束
{
RxState=3;
RxFlag1=1;
Cx=RxBuffer1[RxCounter-5];
Cy=RxBuffer1[RxCounter-4];
Cw=RxBuffer1[RxCounter-3];
Ch=RxBuffer1[RxCounter1-2];
}
}
RxBuffer1是一個(gè)裝有接收OpenMV數(shù)據(jù)的數(shù)組,RxCounter1起著一個(gè)計(jì)數(shù)器的作用,當(dāng)RxBuffer[RxCounter1-1]存放的數(shù)據(jù)為數(shù)據(jù)包的幀位時(shí),說明已經(jīng)接收成功整個(gè)數(shù)據(jù)包,此時(shí)RxBuffer[RxCounter1-2]存放ch坐標(biāo)值,RxBuffer[RxCounter1-3]存放cw坐標(biāo)值,RxBuffer[RxCounter1-4]存放cy坐標(biāo)值,RxBuffer[RxCounter1-5]存放cx坐標(biāo)值,此后在RxState=3過程中將這四個(gè)坐標(biāo)顯示出來即可。
特別注意的是:STM32中斷每發(fā)生一次,只會接收到一字節(jié)的數(shù)據(jù),因此,進(jìn)行七次才會接收完一整幀的數(shù)據(jù)包,這一點(diǎn)需要讀者仔細(xì)揣摩,結(jié)合上文中說的靜態(tài)變量關(guān)鍵字static,定義了:
u8 com_data;
u8 i;
static u8 RxCounter1=0;
static u8 RxBuffer1[10]={0};
static u8 RxState = 0;
static u8 RxFlag1 = 0;
請讀者仔細(xì)揣摩為什么com_data(端口接收到的數(shù)據(jù))、i定義的是動態(tài)的(auto),而RxBuffer1(裝接收到數(shù)據(jù)的靜態(tài)全局?jǐn)?shù)組)、RxState(狀態(tài)標(biāo)志變量)、RxFlag1(接受結(jié)束標(biāo)志變量)定義的確實(shí)靜態(tài)的,這一點(diǎn)并不難理解。
5.利用PC端測試數(shù)據(jù)數(shù)據(jù)是否發(fā)送接收正常
在進(jìn)行OpenMV與STM32的通信測試過程中,我使用了USB轉(zhuǎn)TTL模塊,將OpenMV(或STM32單片機(jī))與PC端進(jìn)行通信確保數(shù)據(jù)發(fā)出或者接收正常。
OpenMV&&PC
OpenMV_RX接模塊TX
OpenMV_TX接模塊RX
OpenMV_GND接模塊GND
然后打開OpenMV,在大循環(huán)while(True)中使用語句:
DATA=bytearray[(1,2,3,4,5)] uart.write(DATA)
打開PC端串口助手,注意設(shè)置一樣的波特率、停止位、發(fā)送字節(jié)數(shù)等,查看串口助手是否接受到了數(shù)據(jù)。
STM32&&PC
STM32_RX接模塊TX
STM32_TX接模塊RX
STM32_GND接模塊GND
注意:不管是STM32與PC還是OpenMV與PC還是STM32與OpenMV通信,都要將二者的GND連接在一起。
在main.c中先調(diào)用stdio頭文件,大循環(huán)中使用如下語句:
while(1)
{
printf("HelloWorld!");
}
打開串口助手查看是否接收到了數(shù)據(jù)。
6.學(xué)習(xí)補(bǔ)充 (代碼看不懂的時(shí)候可以來看一下)
補(bǔ)充1:static關(guān)鍵字(靜態(tài)變量)的使用
static 修飾全局函數(shù)和全局變量,只能在本源文件使用。舉個(gè)例子,比如用以下語句static u8 RxBuffer[10] 定義了一個(gè)名為RxBuffer的靜態(tài)數(shù)組,數(shù)組元素類型為unsigned char型。在包含Rxbuffer的源文件中,Rxbuffer相當(dāng)于一個(gè)全局變量,任意地方修改RxBuffer的值,RxBuffer都會隨之改變。而且包含RxBuffer的函數(shù)在多次運(yùn)行后RxBuffer的值會一直保存(除非重新賦值)。在C語言學(xué)習(xí)中,利用static關(guān)鍵字求階乘是一個(gè)很好的例子:
#include“stdio.h”
long fun(int n);
void main()
{
int i,n;
printf("input the value of n:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("%d! = %1d\n",i,fun(i));
}
}
>long fun(int n)
{
static long p=1;
p=p*n;
return p;
}
效果為依次輸出n!(n=1,2,3…n)
這個(gè)例子中,第一次p的值為1,第二次p的值變成了p x n=1 x 2=2,這個(gè)值會一直保存,如果p沒有定義為靜態(tài)類型,那么在第一次運(yùn)算過后p的值會重新被賦值為1,這就是auto型(不聲明默認(rèn)為auto型)與static型的最大區(qū)別。
總結(jié):static關(guān)鍵字定義的變量是全局變量,在static所包含的函數(shù)多次運(yùn)行時(shí),該變量不會被多次初始化,只會初始化一次。
補(bǔ)充2:extern關(guān)鍵字(外部變量)的使用
程序的編譯單位是源程序文件,一個(gè)源文件可以包含一個(gè)或若干個(gè)函數(shù)。在函數(shù)內(nèi)定義的變量是局部變量,而在函數(shù)之外定義的變量則稱為外部變量,外部變量也就是我們所講的全局變量。它的存儲方式為靜態(tài)存儲,其生存周期為整個(gè)程序的生存周期。全局變量可以為本文件中的其他函數(shù)所共用,它的有效范圍為從定義變量的位置開始到本源文件結(jié)束。
如果整個(gè)工程由多個(gè)源文件組成,在一個(gè)源文件中想引用另外一個(gè)源文件中已經(jīng)定義的外部變量,同樣只需在引用變量的文件中用 extern 關(guān)鍵字加以聲明即可。下面就來看一個(gè)多文件的示例:
/****max.c****/
#include <stdio.h>
/*外部變量聲明*/
extern int g_X ;
extern int g_Y ;
int max()
{
return (g_X > g_Y ? g_X : g_Y);
}
/***main.c****/
#include <stdio.h>
/*定義兩個(gè)全局變量*/
int g_X=10;
int g_Y=20;
int max();
int main(void)
{
int result;
result = max();
printf("the max value is %d\n",result);
return 0;
}
運(yùn)行結(jié)果為:
the max value is 20
對于多個(gè)文件的工程,都可以采用上面這種方法來操作。對于模塊化的程序文件,可在其文件中預(yù)先留好外部變量的接口,也就是只采用 extern 聲明變量,而不定義變量,max.c 文件中的 g_X 與 g_Y 就是如此操作的。比如想要在主函數(shù)中調(diào)用usart.c中的變量x,usart.c中有著這樣的定義:static u8 x=0在usart.h中可以這樣寫:extern u8 x在main.c中包含usart.h頭文件,這樣在編譯的時(shí)候就會在main.c中調(diào)用x外部變量。
總結(jié):extern關(guān)鍵字是外部變量,靜態(tài)類型的全局變量,可以在源文件中調(diào)用其他文件中的變量,在多文件工程中配合頭文件使用。
補(bǔ)充3:MicroPython一些庫函數(shù)的解釋
1.ustruct.pack函數(shù):
import ustruct,在ustruct中
data = ustruct.pack("<bbhhhhb", #格式為倆個(gè)字符倆個(gè)短整型(2字節(jié))
0x2C, #幀頭1
0x12, #幀頭2
int(cx), # up sample by 4 #數(shù)據(jù)1
int(cy), # up sample by 4 #數(shù)據(jù)2
int(cw), # up sample by 4 #數(shù)據(jù)1
int(ch), # up sample by 4 #數(shù)據(jù)2
0x5B)
""bbhhhhb"簡單來說就是要發(fā)送數(shù)據(jù)的聲明,bbhhhhb共七個(gè),代表發(fā)送七個(gè)數(shù)據(jù),對照下面的表,可以知道七個(gè)數(shù)據(jù)按時(shí)序發(fā)送為unsigner char、unsigned char、short、short、short、short、unsigned char。0x2c為數(shù)據(jù)幀的幀頭,即檢測到數(shù)據(jù)流的開始,但是一個(gè)幀頭可能會出現(xiàn)偶然性,因此設(shè)置兩個(gè)幀頭0x2c與0x12以便在中斷中檢測是否檢測到了幀頭以便存放有用數(shù)據(jù)。0x5b為幀尾,即數(shù)據(jù)幀結(jié)束的標(biāo)志。

2.bytearray([ , , , ])函數(shù):
用于把十六進(jìn)制數(shù)據(jù)以字節(jié)形式存放到字節(jié)數(shù)組中,以便以數(shù)據(jù)幀的形式發(fā)送出去進(jìn)行通信。
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B]) uart,write(FH)
7.效果展示(可以先來看效果)
從上到下依次為CX,CY,CW,CH
8.博客更新
1.有朋友反饋OpenMv端找不到色塊就會報(bào)錯,解決方案如下:
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold_01])
cx=0;cy=0;
if blobs:
max_b = find_max(blobs)
#如果找到了目標(biāo)顏色
cx=max_b[5]
cy=max_b[6]
cw=max_b[2]
ch=max_b[3]
img.draw_rectangle(max_b[0:4]) # rect
img.draw_cross(max_b[5], max_b[6]) # cx, cy
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
#sending_data(cx,cy,cw,ch)
uart.write(FH)
print(cx,cy,cw,ch)
在以上代碼中,將max_b = find_max(blobs) 移到if blobs外即可。
2.有朋友反饋OpenMV發(fā)送數(shù)據(jù)只能發(fā)送一個(gè)字節(jié),也就是說大于255的數(shù)據(jù)無法直接通過代碼完成,現(xiàn)在提供以下解決方案:在STM32端代碼中依次保存大于255數(shù)字的高八位和低八位最后在組合在一起即可。
2021/9/15更新 4字節(jié)與浮點(diǎn)數(shù)之間的轉(zhuǎn)換(參考)
#if 1
int main()
{
#if 0
//字符型數(shù)據(jù)分成四個(gè)字節(jié)存放在數(shù)組中
float m = 23.25;
unsigned char *a;
a = (unsigned char *)&m;
printf("0x%x \n0x%x \n0x%x \n0x%x \n",a[0],a[1],a[2],a[3]);
#endif
#if 1
//四個(gè)字節(jié)數(shù)據(jù)合成存放在數(shù)組中
unsigned char a[]={0x00,0x00,0xba,0x41};
float BYTE;
BYTE = *(float *)&a;
printf("%f\n",BYTE);
#endif
}
#endif
上述代碼實(shí)現(xiàn)了將四個(gè)字節(jié)轉(zhuǎn)換為一個(gè)浮點(diǎn)數(shù)的功能,同時(shí)也實(shí)現(xiàn)了將一個(gè)浮點(diǎn)數(shù)拆分為四個(gè)字節(jié)功能。在Openmv傳數(shù)據(jù)時(shí),只能傳輸一個(gè)字節(jié),大于255的數(shù)無法以一字節(jié)形式發(fā)送,因此可以在Openmv端將該數(shù)據(jù)拆分成兩個(gè)字節(jié),分別發(fā)送給Stm32端,同時(shí)Stm32端對傳來的數(shù)據(jù)進(jìn)行合成,合成并解析為對應(yīng)的數(shù)據(jù)。
另一種解決方案:python傳數(shù)據(jù)的1/2,單片機(jī)在乘2即可。
9.參考鏈接
[1]extern外部變量參考鏈接
[2]星瞳科技OpenMV中文參考手冊官方
[3]MicroPython函數(shù)庫
10.完整版代碼鏈接
到此這篇關(guān)于超詳細(xì)OpenMV與STM32單片機(jī)通信 附完整源碼的文章就介紹到這了,更多相關(guān)OpenMV與STM32單片機(jī)通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV圖像卷積之cv.filter2D()函數(shù)詳解
在其官方文檔中,filter2D()函數(shù)在掩模板介紹中一筆帶過,我認(rèn)為該函數(shù)應(yīng)該進(jìn)行詳細(xì)介紹,下面這篇文章主要給大家介紹了關(guān)于OpenCV圖像卷積之cv.filter2D()函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-09-09
Python實(shí)現(xiàn)字典的key和values的交換
本文給大家分別介紹了在python3.0和2.7版本下實(shí)現(xiàn)字典的key和values的交換的程序代碼,非常的簡單實(shí)用,有需要的小伙伴可以參考下。2015-08-08
在python中以相同順序shuffle兩個(gè)list的方法
今天小編就為大家分享一篇在python中以相同順序shuffle兩個(gè)list的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12
Python操作PostgreSQL數(shù)據(jù)庫的基本方法(增刪改查)
PostgreSQL數(shù)據(jù)庫是最常用的關(guān)系型數(shù)據(jù)庫之一,最吸引人的一點(diǎn)是它作為開源數(shù)據(jù)庫且具有可拓展性,能夠提供豐富的應(yīng)用,這篇文章主要給大家介紹了關(guān)于Python操作PostgreSQL數(shù)據(jù)庫的基本方法,文中介紹了連接PostgreSQL數(shù)據(jù)庫,以及增刪改查,需要的朋友可以參考下2023-09-09
詳解用pyecharts Geo實(shí)現(xiàn)動態(tài)數(shù)據(jù)熱力圖城市找不到問題解決
這篇文章主要介紹了詳解用pyecharts Geo實(shí)現(xiàn)動態(tài)數(shù)據(jù)熱力圖城市找不到問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Python設(shè)置Word全局樣式和文本樣式的示例代碼
這篇文章主要介紹了如何利用Python對Word內(nèi)容進(jìn)行各種樣式的設(shè)置,讓其能夠看起來更加的美觀。文中的示例代碼講解詳細(xì),需要的可以參考一下2022-05-05
python socket 超時(shí)設(shè)置 errno 10054
這篇文章主要介紹了python 遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接 socket 超時(shí)設(shè)置 errno 10054 ,需要的朋友可以參考下2014-07-07
Python使用PyQt5/PySide2編寫一個(gè)極簡的音樂播放器功能
這篇文章主要介紹了Python中使用PyQt5/PySide2編寫一個(gè)極簡的音樂播放器功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
圖文講解選擇排序算法的原理及在Python中的實(shí)現(xiàn)
這篇文章主要介紹了選擇排序的原理及在Python中的實(shí)現(xiàn),選擇排序的時(shí)間復(fù)雜度為О(n²),需要的朋友可以參考下2016-05-05
pytorch教程網(wǎng)絡(luò)和損失函數(shù)的可視化代碼示例
這篇文章主要介紹了pytorch教程中網(wǎng)絡(luò)和損失函數(shù)的可視化,文中附含詳細(xì)的代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09

