STM32 se connecte au port série de la caméra OV2640 pour afficher l'interface vidéo sur l'interface PyQt5 et utilise MQTT pour l'affichage.

STM32 connecte la source vidéo OV2640 à l'interface PyQt5
. En tant qu'entrée du modèle AI, le flux vidéo est très important. Dans cet article, nous présenterons comment connecter le STM32 à la caméra OV2640 et connecter le flux vidéo à l'interface PyQt5.

Connexion matérielle
Tout d'abord, nous devons connecter la caméra OV2640 au STM32. Nous pouvons utiliser les méthodes de connexion suivantes :

OV2640 | STM32 ------|------ SIOC | PB8 SIOD | PB9 XCLK | PA8 PCLK | PA6 VSYNC | PA4 HREF | PA7D0 | PC0 D1 | PC1 D2 | PC2 D3 | PC3 D4 | PC4 D5 | PB6 D6 | PB7 D7 | PA9

Code STM32
Ensuite, nous devons écrire le code STM32 pour contrôler la caméra OV2640 et diffuser la vidéo sur le PC. Nous pouvons utiliser le code suivant :

#inclure « stm32f4xx.h »
#inclure « stm32f4xx_gpio.h »
#inclure « stm32f4xx_rcc.h »
#inclure « stm32f4xx_dma.h »
#inclure « stm32f4xx_dcmi.h »

#définir BUFFER_SIZE 320 240 2

tampon uint8_t[BUFFER_SIZE] ;

void DCMI_Config(void)
{ DCMI_InitTypeDef DCMI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure ; DMA_InitTypeDef DMA_InitStructure ;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_DCMI);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &GPIO_InitStructure);

DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);

DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DCMI->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);

DCMI_Cmd(ENABLE);
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_CaptureCmd(ENABLE);

}

int main(void)
{ DCMI_Config();

while (1)
{
}

}
Code PyQt5
Enfin, nous devons écrire du code PyQt5 pour recevoir le flux vidéo transmis par STM32 et l'afficher sur l'interface. Nous pouvons utiliser le code suivant :

importer le système
depuis PyQt5.QtWidgets importer QApplication, QWidget, QLabel
depuis PyQt5.QtGui importer QImage, QPixmap
depuis PyQt5.QtCore importer QTimer
importer la série

ser = série.Série('COM3', 115200)

classe App(QWidget) :
def init (self) :
super(). init ()
self.title = 'Flux vidéo STM32'
self.left = 100
self.top = 100
self.width = 320
self.height = 240
self.initUI()

def initUI(self):
    self.setWindowTitle(self.title)
    self.setGeometry(self.left, self.top, self.width, self.height)

    self.label = QLabel(self)
    self.label.setGeometry(0, 0, self.width, self.height)

    self.timer = QTimer(self)
    self.timer.timeout.connect(self.update_frame)
    self.timer.start(1)

    self.show()

def update_frame(self):
    if ser.in_waiting > 0:
        data = ser.read(320*240*2)
        img = QImage(data, 320, 240, QImage.Format_RGB16)
        pixmap = QPixmap.fromImage(img)
        self.label.setPixmap(pixmap)

if name == ' main ' :
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Dans cet exemple, nous utilisons le contrôle QLabel de PyQt5 pour afficher le flux vidéo. Nous avons également utilisé une minuterie pour mettre à jour périodiquement le flux vidéo. Enfin, nous utilisons le port série pour nous connecter au STM32 et recevoir le flux vidéo.

Résumer

Dans cet article, nous expliquons comment connecter le STM32 à la caméra OV2640 et connecter le flux vidéo à l'interface PyQt5. Cet exemple peut vous aider à comprendre comment utiliser STM32 pour contrôler des périphériques et transférer des données vers un PC.

Si vous utilisez MQTT pour transmettre des flux vidéo
, vous pouvez utiliser le mode publication/abonnement du protocole MQTT. Les étapes spécifiques sont les suivantes :

Écrivez du code sur STM32 pour convertir le flux vidéo en données binaires et publiez les données sur le serveur MQTT à l'aide du protocole MQTT.

Écrivez du code côté PC, utilisez le protocole MQTT pour vous abonner aux données du flux vidéo du serveur MQTT et convertissez les données en flux vidéo pour l'affichage.

Voici un exemple de code simple :

Code STM32 :

#include « stm32f4xx.h »
#include « stm32f4xx_gpio.h »
#include « stm32f4xx_rcc.h »
#include « stm32f4xx_dma.h »
#include « stm32f4xx_dcmi.h »
#include « MQTTClient.h »

#définir BUFFER_SIZE 320 240 2

tampon uint8_t[BUFFER_SIZE] ;

void DCMI_Config(void)
{ DCMI_InitTypeDef DCMI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure ; DMA_InitTypeDef DMA_InitStructure ;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_DCMI);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &GPIO_InitStructure);

DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);

DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DCMI->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);

DCMI_Cmd(ENABLE);
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_CaptureCmd(ENABLE);

}

int main(void)
{ DCMI_Config();

Network network;
MQTTClient client;
NetworkInit(&network);
MQTTClientInit(&client, &network, 30000, NULL, 0, NULL, 0);

char* address = "tcp://localhost:1883";
int rc = NetworkConnect(&network, address, 1883);
if (rc != 0) {
    printf("Failed to connect to MQTT broker: %d

", rc);
renvoie -1;
}

MQTTMessage message;
message.qos = QOS0;
message.retained = 0;
message.payload = buffer;
message.payloadlen = BUFFER_SIZE;

while (1)
{
    rc = MQTTClientPublish(&client, "video_stream", &message);
    if (rc != 0) {
        printf("Failed to publish video stream: %d

", rc);
}
}
}
Code PC :

importer paho.mqtt.client en tant que mqtt
importer cv2
importer numpy en tant que np

def on_connect(client, userdata, flags, rc):
print("Connecté avec le code de résultat "+str(rc))
client.subscribe("video_stream")

def on_message(client, userdata, msg) :
data = np.frombuffer(msg.payload, dtype=np.uint8)
img = cv2.imdecode(data, cv2.IMREAD_COLOR)
cv2.imshow("Video Stream", img)
cv2 .waitKey(1)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)

while True :
client.loop_forever()
Dans cet exemple, nous utilisons la bibliothèque paho-mqtt pour implémenter la fonction de publication/abonnement du protocole MQTT. Dans le code STM32, nous utilisons la bibliothèque MQTTClient pour publier les données du flux vidéo sur le serveur MQTT. Dans le code côté PC, nous avons utilisé la bibliothèque OpenCV pour convertir les données binaires en flux vidéo et utilisé le protocole MQTT pour nous abonner aux données du flux vidéo du serveur MQTT.

Résumer

Dans cet article, nous expliquons comment utiliser le protocole MQTT pour la transmission vidéo en streaming. Cet exemple peut vous aider à comprendre comment utiliser le protocole MQTT pour implémenter le mode publication/abonnement et transmettre les données de streaming vidéo au PC pour affichage.

Guess you like

Origin blog.csdn.net/qq_56152172/article/details/129672576