注 :未经允许请勿转载,请尊重劳动成果,大家都是知识分子!谢谢!
一开始是用原子的STM32F103的战舰开发版,不过在CUBE配置的时候LWIP的配置死活找不到,只有移植原子的例程这一条路,果断换个板子。
硬件:STM32F429IGTx;
软件:STM32CUBEMX,KEIL5
首先先配置LWIP,ETH,RTOS,IIC以及RCC,之所以配置IIC,是因为F429的开发版的芯片结构的问题,是由MCU的IIC总线发出 电平信号给PCF8574这个IO拓展芯片,然后再使能LAN8720。
先看ETH的配置:
注:之前在网上找到的都是关于这个PHY地址的解答,都是要置0,但是其实是有问题的,我的PHY芯片是LAN8270T,在原子的阿波罗开发板上,这个地址是需要置1的。
在设置完PHY芯片之后,就是参数的设置
由于CUBE默认生成的是LAN8722A,但是实际上是8720,所以在这里改过来,至于下面的参数,就需要参考相关手册啦,是不是这样子呢?可以试一下喔。
在这里是选择RMII,选这个的原因参考开发版电路原理图,然后后面的PHY Address这里是浮空的,所以设0。
RTOS我在任务列表里面加了2个任务备用,其他就是常规操作啦,这里就跳过啦
然后是IIC的配置,这里选择的是I2C2,因为这个是GPIOH的PH4和PH5是两根数据线和时钟线
由于是需要使能ETH_RESET引脚,所以需要另外选择IIC_INT引脚,在CUBE里面,PB12这个引脚没有办法直接选择IIC,而是选择IIC_SMBA,这个总线可以说是IIC的子集,具有相同的使用方法
(因为之前从原子的例程里面直接移植过IIC的函数,但是并不能用,可能是底层的时钟不一致,以后有机会再研究了)
然后就是配置LWIP,这个相对来说是比较复杂的,不过并不难
在这里由于是在校园网,所以ping的不是路由器,所以是设置的学校局域网的IP地址,所以没有只能DHCP,然后我这里是使用TCP,所以就把UDP给DISABLE,使能TCP。
RCC部分我就是直接选择常规操作了,前面的博客也有介绍到,不懂的请移步百度
接下来就是时钟树的配置,只要不显示红紫色,即时钟频率在允许的范围内就OK啦
然后就是生成相应的工程啦。
在生成工程后,在主函数里面添加PCF8574.h头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "pcf8574.h"
//#include "ethernetif.h"
/* USER CODE END Includes */
然后再主函数里面加入8574的初始化函数
/* USER CODE BEGIN 2 */
PCF8574_Init();
/* USER CODE END 2 */
接下来就是在RTOS里面,在include 里面加入gpio.h和pcf8574.h两个头文件
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "gpio.h"
#include "pcf8574.h"
//#include "tcp_echoserver.h"
/* USER CODE END Includes */
然后其他的直接看程序啦
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
ETH_HandleTypeDef heth1;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
osThreadId defaultTaskHandle;
osThreadId myTaskTCPHandle;
osThreadId myTaskLEDHandle;
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
// extern void Tcp_Server_Init(void);
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void const * argument);
void TCPTask02(void const * argument);
void LEDTask03(void const * argument);
extern void MX_LWIP_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of myTaskTCP */
osThreadDef(myTaskTCP, TCPTask02, osPriorityIdle, 0, 128);
myTaskTCPHandle = osThreadCreate(osThread(myTaskTCP), NULL);
/* definition and creation of myTaskLED */
osThreadDef(myTaskLED, LEDTask03, osPriorityIdle, 0, 128);
myTaskLEDHandle = osThreadCreate(osThread(myTaskLED), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
// PCF8574_ReadBit(ETH_RESET_IO);
PCF8574_WriteBit(ETH_RESET_IO,1);
HAL_Delay(100);
PCF8574_WriteBit(ETH_RESET_IO,0);
HAL_Delay(100);
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
uint8_t MACAddr[6] ;
heth1.Instance = ETH;
heth1.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
heth1.Init.PhyAddress = LAN8720_PHY_ADDRESS;
// MACAddr[0] = 0x00;
// MACAddr[1] = 0x80;
// MACAddr[2] = 0xE1;
// MACAddr[3] = 0x00;
// MACAddr[4] = 0x00;
// MACAddr[5] = 0x00;
MACAddr[0] = 0x02;
MACAddr[1] = 0x00;
MACAddr[2] = 0x00;
MACAddr[3] = 0x55;
MACAddr[4] = 0x00;
MACAddr[5] = 0x48;
heth1.Init.MACAddr = &MACAddr[0];
heth1.Init.RxMode = ETH_RXINTERRUPT_MODE;
heth1.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
heth1.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
//Tcp_Server_Init();
/* Infinite loop */
for(;;)
{
// MX_LWIP_Process();
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
在RTOS里面搞定程序之后,这里还有一个,由于我在cube里面已经使能了PB12这个引脚,那么我在PCF8574的初始化函数里面把PB12引脚的配置给注释掉,让这个工作在GPIO里面做。
由于我在HAL库里面没有找到us的延时,所以在这里就直接引用了delay.c的延时程序(应该是我懒,懒得找了(╥╯^╰╥))
然后在这里有要说一下的就是,CUBE生成的I2C的文件里面,只有一个初始化函数,其他什么都没有,都是需要自己写的。所以主要的工作量就在这里了其实。然后程序编译,
编译通过,然后通过STLINK下载到班子里,然后ping一下
到这里就搞定啦。
总结:前段时间像无头苍蝇一下乱搞,主要是思路没有理清楚,只要理清楚MCU、PCF8574和LAN8720之间的连接方式,以及芯片的使用方法,就会相对来说顺畅一点,感觉自己有进步了一点,有点开心,今晚回去打个王者吧。
(文章出自:build_oooxf)