STM32
直播中

硕达科讯

7年用户 821经验值
私信 关注
[问答]

如何去实现对STM32芯片的开发板的LED进行灯控制呢

如何去实现对STM32芯片的开发板的LED进行灯控制呢?有什么办法吗?

回帖(1)

李铭鑫

2021-11-3 11:38:48
  本文将在前面mini2440建立的domoticz、mosquitto为服务器的基础上,以Android做远程客户端来实现对STM32芯片的开发板的LED进行灯控制,当然,这是一个基本功能的实现,如果长期使用的话,还需要做很多其他的工作(例如断网重连,重连多少次重启系统等等,还要有个可以在SD卡上读入的硬件配置信息等等)。
  首先展示一下开发板这边情况,硬件方面是在2011年买的“金牛开发板”,主控芯片是STM32F107VC,PHY芯片是DP83848,烧固件的工具是随开发板带来的Jlink,从JTAG口烧录进去。
  软件方面,使用RTThread-2.1.0作为操作系统,该系统自带移植的嵌入式TCP/IP协议栈LwIP。
  本文中使用的LwIP协议栈版本是1.4.1,是rtthread默认bsp中默认的版本。
  bsp工程文件位置:rt-threadbspstm32f107project.uvproj
  bsp已经实现了PHY芯片DP83848的驱动,所以就省了很多事。
  使用的集成开发环境是:MDK 4.11 版本
  本人在工程中是用了对c99的支持(主要是为了调试)。
  本来看介绍,还以为RTThread-2.1.0已经移植好了MQTT客户端程序,但实际上,只是把代码放过来,还没有做什么移植。
  所以,要实现本文的目标,就需要对MQTT客户端做个移植。
  mqtt的客户端程序在rtthread软件包的位置是:
  rt-threadcomponentsexternalpaho-mqtt
  不知道这个是什么版本的,总之,本人是用在mini2440上已经验证过的版本,就是官方在GitHub上的最新版本,封包解包的那部分用MQTTPacket,可以不用改动,直接就用。
  MQTTClient-C这个模块部分,用自己的实现。
  放到rt-threadcomponentsexternalpaho-mqttMQTTClient-Csamplesdomoticz目录下。
  主要实现有三个部分:
  1、对socket的读写的基本操作简单封装。相关内容放到MQTTRTThread.h和MQTTRTThread.c中。
  2、对MQTT连接和消息的解析详细过程。相关内容放到MQTTClient.h和MQTTClient.c中。
  3、对整个过程的控制,使用rtthread的一个线程实现。相关内容放到DomoticzThread.h和DomoticzThread.c中。
  源码放在后面附上。
  接下来要说的内容就是把曾在mini2440上用过的domoticz消息解析框架移植过来。
  果然keil的arm编译器跟GCC是不同的,要做一些改动。改好的源码在后面附上。
  这一部分放在rt-threadbspstm32f107applications目录下。
  在STM32开发板上,也控制了两个LED作为例程。
  效果跟mini2440上的是一样的,以后有时间再上图吧。
  后面有时间把整个工程打包上传上来。
  以下是上述介绍的源码:
  dprintf.h
  #ifndef __DPRINTF_H__
  #define __DPRINTF_H__
  #ifdef __cplusplus
  extern “C”{
  #endif
  #ifdef __DEBUG
  #include 《stdarg.h》
  #include 《string.h》
  //just get file name without the path
  static const char *getCurrentFileName(const char * strFileName)
  {
  const char *p = strrchr(strFileName,‘\’);
  return p==NULL?strFileName:++p;
  }
  #define dprintf(fmt,。..) rt_kprintf(“%s,line:%d,”fmt,getCurrentFileName(__FILE__),__LINE__,##__VA_ARGS__)
  #else
  #define dprintf(fmt,。..)
  #endif
  #ifdef __cplusplus
  }
  #endif
  #endif
  一、MQTTClient-C部分:
  1、MQTTRTThread.h
  #include 《rtthread.h》
  //----------------------------------------------------------
  typedef struct Timer
  {
  rt_tick_t end_tick;
  } Timer;
  void TimerInit(Timer*);
  char TimerIsExpired(Timer*);
  void TimerCountdownMS(Timer*, unsigned int);
  void TimerCountdown(Timer*, unsigned int);
  int TimerLeftMS(Timer*);
  void DeleteTimer(Timer*);
  //-------------------------------------------------------
  typedef struct Network
  {
  int my_socket;
  int (*mqttread) (struct Network*, unsigned char*, int, int);
  int (*mqttwrite) (struct Network*, unsigned char*, int, int);
  } Network;
  void NetworkInit(Network*);
  int NetworkConnect(Network*, char*, int);
  void NetworkDisconnect(Network*);
  MQTTRTThread.c
  #include “MQTTRTThread.h”
  #include 《lwip/netdb.h》
  #include 《lwip/sockets.h》
  #include 《stdio.h》
  //#define __DEBUG
  #include “dprintf.h”
  void TimerInit(Timer* timer)
  {
  timer-》end_tick = 0;
  }
  char TimerIsExpired(Timer* timer)
  {
  return timer-》end_tick 《= rt_tick_get();
  }
  void TimerCountdownMS(Timer* timer, unsigned int timeout)
  {
  timer-》end_tick = rt_tick_get() + timeout*RT_TICK_PER_SECOND/1000;
  }
  void TimerCountdown(Timer* timer, unsigned int timeout)
  {
  timer-》end_tick = rt_tick_get() + timeout*RT_TICK_PER_SECOND;
  }
  int TimerLeftMS(Timer* timer)
  {
  return timer-》end_tick - rt_tick_get() ;
  }
  int RTThreadLwIP_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
  {
  int bytes = 0;
  struct timeval interval ;
  interval.tv_sec = timeout_ms / 1000;
  interval.tv_usec = (timeout_ms % 1000) * 1000;
  if (interval.tv_sec 《 0 || (interval.tv_sec == 0 && interval.tv_usec 《= 0))
  {
  interval.tv_sec = 0;
  interval.tv_usec = 100;
  }
  lwip_setsockopt(n-》my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
  while (bytes 《 len)
  {
  int rc = recv(n-》my_socket, &buffer[bytes], (size_t)(len - bytes), MSG_DONTWAIT);
  if (rc == -1)
  {//dprintf(“errno=%dn”,errno);
  //if (errno != ENOTCONN && errno != ECONNRESET)
  if (errno != ETIMEDOUT && errno != ECONNRESET)
  {
  bytes = -1;
  }
  break;
  }
  else if (rc == 0)
  {
  bytes = 0;
  break;
  }
  else
  bytes += rc;
  }
  return bytes;
  }
  int RTThreadLwIP_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
  {
  int rc;
  struct timeval tv;
  tv.tv_sec = timeout_ms / 1000;
  tv.tv_usec = (timeout_ms % 1000) * 1000;
  if (tv.tv_sec 《 0 || (tv.tv_sec == 0 && tv.tv_usec 《= 0))
  {
  tv.tv_sec = 0;
  tv.tv_usec = 100;
  }
  lwip_setsockopt(n-》my_socket, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv,sizeof(struct timeval));
  rc = lwip_write(n-》my_socket, buffer, len);
  return rc;
  }
  void NetworkInit(Network* n)
  {
  n-》my_socket = 0;
  n-》mqttread = RTThreadLwIP_read;
  n-》mqttwrite = RTThreadLwIP_write;
  }
  int NetworkConnect(Network* n, char* addr, int port)
  {
  struct hostent *host;
  struct in_addr ip_addr;
  struct sockaddr_in sockaddr;
  int rc = -1;
  // 第一步 DNS地址解析
  rt_kprintf(“calling gethostbyname with: %srn”, addr);
  host = gethostbyname(addr);
  ip_addr.s_addr = *(unsigned long *) host-》h_addr_list[0];
  rt_kprintf(“MQTTThread IP Address:%srn” , inet_ntoa(ip_addr));
  sockaddr.sin_family = AF_INET;
  sockaddr.sin_port = htons(port);
  sockaddr.sin_addr = ip_addr;
  rt_memset(&(sockaddr.sin_zero), 0, sizeof(sockaddr.sin_zero));
  // 第二步 创建套接字
  n-》my_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (n-》my_socket != -1)
  {
  rt_kprintf(“n-》my_socket: %drn”, n-》my_socket);
  rc = lwip_connect(n-》my_socket, (struct sockaddr*)&sockaddr, sizeof(struct sockaddr));
  if (rc == -1)
  {
  rt_kprintf(“Connect fail!n”);
  lwip_close(n-》my_socket);
  //rt_free(recv_data);
  }
  else
  {
  rt_kprintf(“Connect success!n”);
  }
  }
  return rc;
  }
  void NetworkDisconnect(Network* n)
  {
  lwip_close(n-》my_socket);
  }
  2、MQTTClient.h
  /*******************************************************************************
  * Copyright (c) 2014, 2017 IBM Corp.
  *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
  *
  * The Eclipse Public License is available at
  * http://www.eclipse.org/legal/epl-v10.html
  * and the Eclipse Distribution License is available at
  * http://www.eclipse.org/org/documents/edl-v10.php.
  *
  * Contributors:
  * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
  * Ian Craggs - documentation and platform specific header
  * Ian Craggs - add setMessageHandler function
  *******************************************************************************/
  #if !defined(MQTT_CLIENT_H)
  #define MQTT_CLIENT_H
  #if defined(__cplusplus)
  extern “C” {
  #endif
  #if defined(WIN32_DLL) || defined(WIN64_DLL)
  #define DLLImport __declspec(dllimport)
  #define DLLExport __declspec(dllexport)
  #elif defined(LINUX_SO)
  #define DLLImport extern
  #define DLLExport __attribute__ ((visibility (“default”)))
  #else
  #define DLLImport
  #define DLLExport
  #endif
  #include “MQTTPacket.h”
  #include “MQTTRTThread.h”
  #include “stdio.h”
  #if defined(MQTTCLIENT_PLATFORM_HEADER)
  /* The following sequence of macros converts the MQTTCLIENT_PLATFORM_HEADER value
  * into a string constant suitable for use with include.
  */
  #define xstr(s) str(s)
  #define str(s) #s
  #include xstr(MQTTCLIENT_PLATFORM_HEADER)
  #endif
  #define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */
  #if !defined(MAX_MESSAGE_HANDLERS)
  #define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */
  #endif
  enum QoS { QOS0, QOS1, QOS2, SUBFAIL=0x80 };
  /* all failure return codes must be negative */
  enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
  /* The Platform specific header must define the Network and Timer structures and functions
  * which operate on them.
  *
  typedef struct Network
  {
  int (*mqttread)(Network*, unsigned char* read_buffer, int, int);
  int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int);
  } Network;*/
  /* The Timer structure must be defined in the platform specific header,
  * and have the following functions to operate on it. */
  extern void TimerInit(Timer*);
  extern char TimerIsExpired(Timer*);
  extern void TimerCountdownMS(Timer*, unsigned int);
  extern void TimerCountdown(Timer*, unsigned int);
  extern int TimerLeftMS(Timer*);
  typedef struct MQTTMessage
  {
  enum QoS qos;
  unsigned char retained;
  unsigned char dup;
  unsigned short id;
  void *payload;
  size_t payloadlen;
  } MQTTMessage;
  typedef struct MessageData
  {
  MQTTMessage* message;
  MQTTString* topicName;
  } MessageData;
  typedef struct MQTTConnackData
  {
  unsigned char rc;
  unsigned char sessionPresent;
  } MQTTConnackData;
  typedef struct MQTTSubackData
  {
  enum QoS grantedQoS;
  } MQTTSubackData;
  typedef void (*messageHandler)(MessageData*);
  typedef struct MQTTClient
  {
  unsigned int next_packetid,
  command_timeout_ms;
  size_t buf_size,
  readbuf_size;
  unsigned char *buf,
  *readbuf;
  unsigned int keepAliveInterval;
  char ping_outstanding;
  int ping_timeout_times;
  int isconnected;
  int cleansession;
  struct MessageHandlers
  {
  const char* topicFilter;
  void (*fp) (MessageData*);
  } messageHandlers[MAX_MESSAGE_HANDLERS]; /* Message handlers are indexed by subscription topic */
  void (*defaultMessageHandler) (MessageData*);
  Network* ipstack;
  Timer last_sent, last_received;
  #if defined(MQTT_TASK)
  Mutex mutex;
  Thread thread;
  #endif
  } MQTTClient;
  #define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
  /**
  * Create an MQTT client object
  * @param client
  * @param network
  * @param command_timeout_ms
  * @param
  */
  DLLExport void MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms,
  unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size);
  /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
  * The nework object must be connected to the network endpoint before calling this
  * @param options - connect options
  * @return success code
  */
  DLLExport int MQTTConnectWithResults(MQTTClient* client, MQTTPacket_connectData* options,
  MQTTConnackData* data);
  /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
  * The nework object must be connected to the network endpoint before calling this
  * @param options - connect options
  * @return success code
  */
  DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options);
  /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
  * @param client - the client object to use
  * @param topic - the topic to publish to
  * @param message - the message to send
  * @return success code
  */
  DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*);
  /** MQTT SetMessageHandler - set or remove a per topic message handler
  * @param client - the client object to use
  * @param topicFilter - the topic filter set the message handler for
  * @param messageHandler - pointer to the message handler function or NULL to remove
  * @return success code
  */
  DLLExport int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler);
  /** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
  * @param client - the client object to use
  * @param topicFilter - the topic filter to subscribe to
  * @param message - the message to send
  * @return success code
  */
  DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler);
  /** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
  * @param client - the client object to use
  * @param topicFilter - the topic filter to subscribe to
  * @param message - the message to send
  * @param data - suback granted QoS returned
  * @return success code
  */
  DLLExport int MQTTSubscribeWithResults(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler, MQTTSubackData* data);
  /** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning.
  * @param client - the client object to use
  * @param topicFilter - the topic filter to unsubscribe from
  * @return success code
  */
  DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter);
  /** MQTT Disconnect - send an MQTT disconnect packet and close the connection
  * @param client - the client object to use
  * @return success code
  */
  DLLExport int MQTTDisconnect(MQTTClient* client);
  /** MQTT Yield - MQTT background
  * @param client - the client object to use
  * @param time - the time, in milliseconds, to yield for
  * @return success code
  */
  DLLExport int MQTTYield(MQTTClient* client, int time);
  /** MQTT isConnected
  * @param client - the client object to use
  * @return truth value indicating whether the client is connected to the server
  */
  DLLExport int MQTTIsConnected(MQTTClient* client);
  DLLExport int keepalive(MQTTClient* client);
  void MQTTCleanSession(MQTTClient* c);
  #if defined(MQTT_TASK)
  /** MQTT start background thread for a client. After this, MQTTYield should not be called.
  * @param client - the client object to use
  * @return success code
  */
  DLLExport int MQTTStartTask(MQTTClient* client);
  #endif
  #if defined(__cplusplus)
  }
  #endif
  #endif
举报

更多回帖

发帖
×
20
完善资料,
赚取积分