【小安派R2测评】安信可小安派R2+LVGL+FAT+WIFI TCP/IP通信

[复制链接]
查看166 | 回复8 | 前天 21:32 | 显示全部楼层 |阅读模式
本帖最后由 及辰 于 2024-10-16 21:32 编辑

一、产品开箱
首先感谢安信可赠送的小安派。
开箱视频如下:
小安派R2测评---开箱_哔哩哔哩_bilibili
物品清单:

小安派R2清单

小安派R2清单

里面包括:小安派 R2 开发板*1,摄像头模组-酷视 CV031C50 *1,4 寸触摸显示屏-优奕 UE040WV *1,65dB 咪头 *1,8R2W 扬声器 *2,及连接线 2 条。
问题:内部包装十分十分仔细,但是外包装纸壳太软,容易导致内部硬件损坏。

二、环境搭建
本次编译采用的是VScode,环境搭建参考:零基础搭建小安派Windows 开发环境 - 小安派&M61环境搭建、编译烧录教程 - 物联网开发者社区-安信可论坛 - Powered by Discuz! (ai-thinker.com)
其中编译的时候遇到问题:
屏幕截图 2024-10-14 220338.png
这个问题的解决办法为:打开aithinker_Ai-M6X_SDK\project.build文件,编辑它,对第75和76行开头加上“#”,意思是注释掉这2行,记得保存.

修改后代码如下
#        cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/edata.bin build/build_out
#        cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/Rx_boot2_m61.bin build/build_out

三、例程测试
此时测试例程,由于没有板载LED(这里还是比较推荐有一个板载LED),否则没有屏幕还真不好测试板子是否正常。先对板载例程进行测试,视频如下:
949172097f317df2f7a3a3dcb11395d1.gif
重新烧录LVGL官方例程,代码编译采用make,烧录采用make flash COMX=COM3,其中COM3是当前连接开发板的端口,采用USB转TTL,连线图如下:
图片1.png
例程运行视频如下:
小安派R2测评---官方dome演示_哔哩哔哩_bilibili
四、LVGL搭建与测试
LVGL搭建在原本的例程AiPi-Eyes-Rx上进行修改,由于这里LVGL已经配置完成,下载guiguider后,进行自己的屏幕设计,设计完成后点击生成代码,然后将generated文件夹替换demos\ai_lvgl\src\generated即可。具体操作方法及效果演示见视频:
小安派R2测评---LVGL_哔哩哔哩_bilibili
五、SPI读取TF卡及FATFS文件系统
用连接线连接板载SPI接口和TF卡模块(或者焊接背面的TF卡卡槽)注意修改相应的接口,连接图如下:
图片2.png
SPI初始化代码参考aithinker_Ai-M6X_SDK\examples\peripherals\spi\spi_poll,其中关键代码,及需要修改如下:
SPI代码部分,这个自己创建和文件书写就可以。
  1. void spi_isr(int irq, void *arg)
  2. {
  3.     uint32_t intstatus = bflb_spi_get_intstatus(spi0);
  4.     if (intstatus & SPI_INTSTS_TC) {
  5.         bflb_spi_int_clear(spi0, SPI_INTCLR_TC);
  6.         //printf("tc done\r\n");
  7.         spi_tc_done_count++;
  8.     }
  9.     if (intstatus & SPI_INTSTS_TX_FIFO) {
  10.         //printf("tx fifo\r\n");
  11.     }
  12.     if (intstatus & SPI_INTSTS_RX_FIFO) {
  13.         //printf("rx fifo\r\n");
  14.     }
  15. }

  16. void SPI_init(u32 freqm)
  17. {
  18.     struct bflb_spi_config_s spi_cfg =
  19.     {
  20. #if (SPI_CASE_SELECT == SPI_MASTER_CASE)
  21.         .freq = freqm,
  22.         .role = SPI_ROLE_MASTER,
  23. #else
  24.         .freq = 32 * 1000 * 1000,
  25.         .role = SPI_ROLE_SLAVE,
  26. #endif
  27.         .mode = SPI_MODE3,
  28.         .data_width = SPI_DATA_WIDTH_8BIT,
  29.         .bit_order = SPI_BIT_MSB,
  30.         .byte_order = SPI_BYTE_LSB,
  31.         .tx_fifo_threshold = 0,
  32.         .rx_fifo_threshold = 0,
  33.     };
  34.     spi0 = bflb_device_get_by_name("spi0");
  35.     bflb_spi_init(spi0, &spi_cfg);
  36.     bflb_spi_tcint_mask(spi0, false);
  37.     bflb_irq_attach(spi0->irq_num, spi_isr, NULL);
  38.     bflb_irq_enable(spi0->irq_num);
  39.     bflb_spi_feature_control(spi0, SPI_CMD_SET_CS_INTERVAL, 0);

  40. }
复制代码
打开board.h,修改
  1. void board_spi0_gpio_init()
  2. {
  3.     struct bflb_device_s* gpio;

  4.     gpio = bflb_device_get_by_name("gpio");
  5.     /* spi cs */
  6.     bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  7.     /* spi clk */
  8.     bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  9.     /* spi miso */
  10.     bflb_gpio_init(gpio, GPIO_PIN_22, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  11.     /* spi mosi */
  12.     bflb_gpio_init(gpio, GPIO_PIN_15, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
  13. }
复制代码
SPI读取TF卡代码如下:
  1. u8 SD_Initialize(void)
  2. {
  3.     u8 r1;                              // 存放SD卡的返回值
  4.     u16 retry;                          // 用来进行超时计数
  5.     u8 buf[4];
  6.     u16 i;
  7.     SPI_init(281000);             //设置到低速模式

  8.     SD_DisSelect();
  9.     for(i=0;i<10;i++)
  10.     {
  11.         SD_SPI_ReadWriteByte(0XFF);                //发送最少74个脉冲
  12.     }
  13.     retry=20;
  14.     do
  15.     {
  16.         r1=SD_SendCmd(CMD0,0,0x95);     //进入IDLE状态
  17.     }while((r1!=0X01) && retry--);
  18.     SD_DisSelect();
  19.     SD_Type=0;                          //默认无卡
  20.     if(r1==0X01)
  21.     {
  22.         r1=SD_SendCmd(CMD8,0x1AA,0x87);
  23.         if(r1==1)
  24.         {
  25.             for(i=0;i<4;i++)
  26.             {
  27.                 buf[i]=SD_SPI_ReadWriteByte(0xFF);
  28.             }
  29.             SD_DisSelect();
  30.             if(buf[2]==0X01&&buf[3]==0XAA)
  31.             {
  32.                 retry=0XFFFE;
  33.                 do
  34.                 {
  35.                     r1=SD_SendCmd(CMD55,0,0x01);   //发送CMD55
  36.                     r1=SD_SendCmd(0x69,0x40000000,0x01);//发送CMD41
  37.                     SD_DisSelect();
  38.                 }while(r1&&retry--);
  39.                 if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
  40.                 {
  41.                     for(i=0;i<4;i++)
  42.                     {
  43.                         buf[i]=SD_SPI_ReadWriteByte(0xFF);
  44.                     }
  45.                     SD_DisSelect();
  46.                     if(buf[0]&0x40)
  47.                     {
  48.                         SD_Type=SD_TYPE_V2HC;    //检查CCS
  49.                     }
  50.                     else
  51.                     {
  52.                         SD_Type=SD_TYPE_V2;
  53.                     }
  54.                 }

  55.             }
  56.         }
  57.         else//SD V1.x/ MMC  V3
  58.         {
  59.             SD_SendCmd(CMD55,0,0X01);       //发送CMD55
  60.             r1=SD_SendCmd(CMD41,0,0X01);    //发送CMD41
  61.             SD_DisSelect();
  62.             if(r1<=1)
  63.             {
  64.                 SD_Type=SD_TYPE_V1;
  65.                 retry=0XFFFE;
  66.                 do //等待退出IDLE模式
  67.                 {
  68.                     SD_SendCmd(CMD55,0,0X01);   //发送CMD55
  69.                     r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
  70.                     SD_DisSelect();
  71.                 }while(r1&&retry--);
  72.             }
  73.             else//MMC卡不支持CMD55+CMD41识别
  74.             {
  75.                 SD_Type=SD_TYPE_MMC;//MMC V3
  76.                 retry=0XFFFE;
  77.                 do //等待退出IDLE模式
  78.                 {
  79.                     r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
  80.                     SD_DisSelect();
  81.                 }while(r1&&retry--);
  82.             }
  83.             r1=SD_SendCmd(CMD16,512,0X01);
  84.             SD_DisSelect();
  85.             if(retry==0||r1!=0)
  86.             {
  87.                 SD_Type=SD_TYPE_ERR;//错误的卡
  88.             }
  89.         }
  90.     }
  91.     SD_DisSelect();
  92.     SPI_init(16000000);
  93.     if(SD_Type)
  94.     {
  95.         return 0;
  96.     }
  97.     else if(r1)
  98.     {
  99.         return r1;
  100.     }
  101.     return 0xaa;//其他错误
  102. }
复制代码
  1. u8 SD_SPI_ReadWriteByte(u8 data)
  2. {
  3.     u8 retnum;
  4.     Spi_Send_Read_Data_Arr(&data,&retnum,1);
  5.     return retnum;
  6. }

  7. void SD_DisSelect(void)
  8. {
  9.     SD_SPI_ReadWriteByte(0XFF);//提供额外的8个时钟
  10. }

  11. u8 SD_WaitReady(void)
  12. {
  13.     u32 t=0;
  14.     u8 rStr=0;
  15.     do
  16.     {
  17.         rStr=SD_SPI_ReadWriteByte(0xFF);
  18.         if(rStr==0XFF)
  19.         {
  20.             return 0;//OK
  21.         }
  22.         t++;
  23.     }while(t<0XFFFFFF);//等待
  24.     return 1;
  25. }

  26. u8 SD_Select(void)
  27. {
  28.     if(SD_WaitReady()==0)
  29.     {
  30.         return 0;//等待成功
  31.     }
  32.     SD_DisSelect();
  33.     return 1;//等待失败
  34. }

  35. u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
  36. {
  37.     u8 r1;
  38.     u8 Retry=0;
  39.     SD_DisSelect();
  40.     if(SD_Select())return 0XFF;//片选失效
  41.     //发送
  42.     SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
  43.     SD_SPI_ReadWriteByte((u8)(arg >> 24));
  44.     SD_SPI_ReadWriteByte((u8)(arg >> 16));
  45.     SD_SPI_ReadWriteByte((u8)(arg >> 8));
  46.     SD_SPI_ReadWriteByte((u8)(arg));
  47.     SD_SPI_ReadWriteByte(crc);
  48.     if(cmd==12)
  49.     {
  50.         SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
  51.     }
  52.     //等待响应,或超时退出
  53.     Retry=0X1F;
  54.     do
  55.     {
  56.         r1=SD_SPI_ReadWriteByte(0xFF);
  57.     }while((r1&0X80) && Retry--);
  58.     //返回状态值
  59.     return r1;
  60. }
复制代码
  1. u8 SD_RecvData(u8*buf,u16 len)
  2. {
  3.     if(SD_GetResponse(0xFE))        //等待SD卡发回数据起始令牌0xFE
  4.     {
  5.         return 1;
  6.     }
  7.     while(len--)//开始接收数据
  8.     {
  9.         *buf=SD_SPI_ReadWriteByte(0xFF);
  10.         buf++;
  11.     }
  12.     //下面是2个伪CRC(dummy CRC)
  13.     SD_SPI_ReadWriteByte(0xFF);
  14.     SD_SPI_ReadWriteByte(0xFF);
  15.     return 0;//读取成功
  16. }

  17. u8 SD_GetResponse(u8 Response)
  18. {
  19.     u16 Count=0xFFFF;//等待次数
  20.     while ((SD_SPI_ReadWriteByte(0xFF)!=Response)&&Count)       //等待得到准确的回应
  21.     {
  22.         Count--;
  23.     }
  24.     if (Count==0)
  25.     {
  26.         return MSD_RESPONSE_FAILURE;        //得到回应失败
  27.     }
  28.     else
  29.     {
  30.         return MSD_RESPONSE_NO_ERROR;       //正确回应
  31.     }
  32. }

  33. u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
  34. {
  35.     u8 r1;
  36.     if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;      //转换为字节地址
  37.     if(cnt==1)
  38.     {
  39.         r1=SD_SendCmd(CMD17,sector,0X01);       //读命令
  40.         if(r1==0)                               //指令发送成功
  41.         {
  42.             r1=SD_RecvData(buf,512);            //接收512个字节
  43.         }
  44.     }
  45.     else
  46.     {
  47.         r1=SD_SendCmd(CMD18,sector,0X01);       //连续读命令
  48.         do
  49.         {
  50.             r1=SD_RecvData(buf,512);            //接收512个字节
  51.             buf+=512;
  52.         }while(--cnt && r1==0);
  53.         SD_SendCmd(CMD12,0,0X01);               //发送停止命令
  54.     }
  55.     SD_DisSelect();                             //取消片选
  56.     return r1;
  57. }

  58. u8 SD_WriteDisk(u8 *buf,u32 sector,u8 cnt)
  59. {
  60.     u8 r1;
  61.     if(SD_Type!=SD_TYPE_V2HC)sector *= 512;     //转换为字节地址
  62.     if(cnt==1)
  63.     {
  64.         r1=SD_SendCmd(CMD24,sector,0X01);       //读命令
  65.         if(r1==0)                               //指令发送成功
  66.         {
  67.             r1=SD_SendBlock(buf,0xFE);          //写512个字节
  68.         }
  69.     }
  70.     else
  71.     {
  72.         if(SD_Type!=SD_TYPE_MMC)
  73.         {
  74.             SD_SendCmd(CMD55,0,0X01);
  75.             SD_SendCmd(CMD23,cnt,0X01);         //发送指令
  76.         }
  77.         r1=SD_SendCmd(CMD25,sector,0X01);       //连续读命令
  78.         if(r1==0)
  79.         {
  80.             do
  81.             {
  82.                 r1=SD_SendBlock(buf,0xFC);      //接收512个字节
  83.                 buf+=512;
  84.             }while(--cnt && r1==0);
  85.             r1=SD_SendBlock(0,0xFD);            //接收512个字节
  86.         }
  87.     }
  88.     SD_DisSelect();                             //取消片选
  89.     return r1;
  90. }

  91. u8 SD_SendBlock(u8*buf,u8 cmd)
  92. {
  93.     u16 t;
  94.     if(SD_WaitReady())return 1;//等待准备失效
  95.     SD_SPI_ReadWriteByte(cmd);
  96.     if(cmd!=0XFD)//不是结束指令
  97.     {
  98.         for(t=0;t<512;t++)
  99.         {
  100.             SD_SPI_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
  101.         }
  102.         SD_SPI_ReadWriteByte(0xFF);//忽略crc
  103.         SD_SPI_ReadWriteByte(0xFF);
  104.         t=SD_SPI_ReadWriteByte(0xFF);//接收响应
  105.         if((t&0x1F)!=0x05)return 2;//响应错误
  106.     }
  107.     return 0;//写入成功
  108. }
复制代码
FATFS系统修改代码块如下:
打开diskio.c,修改如下部分:
disk_initialize函数:
  1. case SD_CARD://SD卡
  2.         res = SD_Initialize();//SD_Initialize()
  3.         if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
  4.         {
  5.             SPI_init(281000);
  6.             SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
  7.             SPI_init(16000000);
  8.         }
  9.         break;
复制代码
disk_read函数:
  1. case SD_CARD://SD卡
  2.         res=SD_ReadDisk(buff,sector,(u8)count);
  3.         if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
  4.         {
  5.             SPI_init(281000);
  6.             SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
  7.             SPI_init(16000000);
  8.         }
  9.         break;
复制代码
disk_write函数:
  1. case SD_CARD://SD卡
  2.         res=SD_WriteDisk((u8*)buff,sector,(u8)count);
  3.         break;
复制代码
disk_ioctl函数:
  1. if(pdrv==SD_CARD)//SD卡
  2.     {
  3.         switch(cmd)
  4.         {
  5.         case CTRL_SYNC:
  6.             SD_Select();
  7.             if(SD_WaitReady()==0)
  8.                 res = RES_OK;
  9.             else
  10.                 res = RES_ERROR;
  11.             SD_DisSelect();
  12.             break;
  13.         case GET_SECTOR_SIZE:
  14.             *(WORD*)buff = 512;
  15.             res = RES_OK;
  16.             break;
  17.         case GET_BLOCK_SIZE:
  18.             *(WORD*)buff = 8;
  19.             res = RES_OK;
  20.             break;
  21.         case GET_SECTOR_COUNT:
  22.             *(DWORD*)buff = SD_GetSectorCount();
  23.             res = RES_OK;
  24.             break;
  25.         default:
  26.             res = RES_PARERR;
  27.             break;
  28.         }
  29.     }
复制代码
get_fattime函数:
  1. DWORD get_fattime (void)
  2. {
  3.     //rtc_time_t RTC_Timer;
  4.     //R_RTC_CalendarTimeGet (rtc.p_ctrl, &RTC_Timer);     //获取RTC计数时间
  5.     return (DWORD)((81-80)<<25|                //年
  6.     (10+1)<<21|                               //月
  7.     (21+1)<<16|                              //日
  8.     12<<11|                              //时
  9.     21<<5|                                //分
  10.     22);                                   //秒
  11. }
复制代码
如果有系统时间,可以把系统时间放进去,如果没有直接随便给一个就行。
文件系统的其他文件直接复制到文件夹内就可以使用了,具体接口如下:
  1. FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);                                /* Open or create a file */
  2. FRESULT f_close (FIL* fp);                                                                                        /* Close an open file object */
  3. FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);                        /* Read data from the file */
  4. FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);        /* Write data to the file */
  5. FRESULT f_lseek (FIL* fp, FSIZE_t ofs);                                                                /* Move file pointer of the file object */
  6. FRESULT f_truncate (FIL* fp);                                                                                /* Truncate the file */
  7. FRESULT f_sync (FIL* fp);                                                                                        /* Flush cached data of the writing file */
  8. FRESULT f_opendir (DIR* dp, const TCHAR* path);                                                /* Open a directory */
  9. FRESULT f_closedir (DIR* dp);                                                                                /* Close an open directory */
  10. FRESULT f_readdir (DIR* dp, FILINFO* fno);                                                        /* Read a directory item */
  11. FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);        /* Find first file */
  12. FRESULT f_findnext (DIR* dp, FILINFO* fno);                                                        /* Find next file */
  13. FRESULT f_mkdir (const TCHAR* path);                                                                /* Create a sub directory */
  14. FRESULT f_unlink (const TCHAR* path);                                                                /* Delete an existing file or directory */
  15. FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);        /* Rename/Move a file or directory */
  16. FRESULT f_stat (const TCHAR* path, FILINFO* fno);                                        /* Get file status */
  17. FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);                        /* Change attribute of a file/dir */
  18. FRESULT f_utime (const TCHAR* path, const FILINFO* fno);                        /* Change timestamp of a file/dir */
  19. FRESULT f_chdir (const TCHAR* path);                                                                /* Change current directory */
  20. FRESULT f_chdrive (const TCHAR* path);                                                                /* Change current drive */
  21. FRESULT f_getcwd (TCHAR* buff, UINT len);                                                        /* Get current directory */
  22. FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);        /* Get number of free clusters on the drive */
  23. FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);        /* Get volume label */
  24. FRESULT f_setlabel (const TCHAR* label);                                                        /* Set volume label */
  25. FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);        /* Forward data to the stream */
  26. FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt);                                        /* Allocate a contiguous block to the file */
  27. FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);                        /* Mount/Unmount a logical drive */
  28. FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len);        /* Create a FAT volume */
  29. FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work);                /* Divide a physical drive into some partitions */
  30. FRESULT f_setcp (WORD cp);                                                                                        /* Set current code page */
  31. int f_putc (TCHAR c, FIL* fp);                                                                                /* Put a character to the file */
  32. int f_puts (const TCHAR* str, FIL* cp);                                                                /* Put a string to the file */
  33. int f_printf (FIL* fp, const TCHAR* str, ...);                                                /* Put a formatted string to the file */
  34. TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);                                                /* Get a string from the file */
复制代码
小安派R2测评---LVGL效果_哔哩哔哩_bilibili

六、WIFI连接与TCP/IP通信
WIFI连接初始化及WIFI连接代码参考:aithinker_Ai-M6X_SDK\examples\wifi\sta\wifi_tcp,其中需要注意关键代码如下:
  1. uint8_t wifi_connect(char* ssid, char* passwd)
  2. {
  3.     int ret = 255;
  4.     // struct fhost_vif_ip_addr_cfg ip_cfg = { 0 };
  5.     uint32_t ipv4_addr = 0;

  6.     scan_item_cb_t resd;
  7.     char we1;
  8.     char we2;

  9.     if (NULL==ssid || 0==strlen(ssid)) {
  10.         return 1;
  11.     }

  12.     if (wifi_mgmr_sta_state_get() == 1) {
  13.         wifi_sta_disconnect();
  14.     }
  15.     printf("wait000");
  16.     //wifi_mgmr_scan_ap_all(&we1,&we2,resd);
  17.     if (wifi_sta_connect(ssid, passwd, NULL, NULL, 0, 0, 0, 1))
  18.     //if (wifi_mgmr_sta_quickconnect(ssid, passwd,  0, 0))
  19.     {
  20.         return 4;
  21.     }
  22.     LOG_I("Wating wifi connet");
  23.     //等待连接成功
  24.     sta_ConnectStatus = 0;
  25.     for (int i = 0;i<10*30;i++) {

  26.         vTaskDelay(100/portTICK_PERIOD_MS);
  27.         switch (sta_ConnectStatus) {
  28.             case CODE_WIFI_ON_MGMR_DONE:
  29.                 return 3;
  30.             case CODE_WIFI_ON_SCAN_DONE:

  31.                 return 2;
  32.             case CODE_WIFI_ON_DISCONNECT:        //连接失败(超过了重连次数还没有连接成功的状态)

  33.                 return 4;
  34.             case CODE_WIFI_ON_CONNECTED:        //连接成功(表示wifi sta状态的时候表示同时获取IP(DHCP)成功,或者使用静态IP)
  35.                 LOG_I("Wating wifi connet OK");
  36.                 break;
  37.             case CODE_WIFI_ON_GOT_IP:

  38.                 return 0;
  39.             default:
  40.                 //等待连接成功
  41.                 break;
  42.         }

  43.     }

  44.     return 14; //连接超时
  45. }
复制代码
  1. int wifi_start_firmware_task(void)
  2. {
  3.     LOG_I("Starting wifi ...");

  4.     /* enable wifi clock */

  5.     GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_IP_WIFI_PHY | GLB_AHB_CLOCK_IP_WIFI_MAC_PHY | GLB_AHB_CLOCK_IP_WIFI_PLATFORM);
  6.     GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_WIFI);

  7.     /* set ble controller EM Size */

  8.     GLB_Set_EM_Sel(GLB_WRAM160KB_EM0KB);

  9.     if (0 != rfparam_init(0, NULL, 0)) {
  10.         LOG_I("PHY RF init failed!");
  11.         return 0;
  12.     }

  13.     LOG_I("PHY RF init success!");

  14.     /* Enable wifi irq */

  15.     extern void interrupt0_handler(void);
  16.     bflb_irq_attach(WIFI_IRQn, (irq_callback)interrupt0_handler, NULL);
  17.     bflb_irq_enable(WIFI_IRQn);

  18.     xTaskCreate(wifi_main, (char*)"fw", WIFI_STACK_SIZE, NULL, TASK_PRIORITY_FW, &wifi_fw_task);

  19.     return 0;
  20. }
  21. /**
  22. * @brief wifi event handler
  23. *      WiFi 事件回调
  24. *
  25. * @param code
  26. */


  27. void wifi_event_handler(uint32_t code)
  28. {

  29.     sta_ConnectStatus = code;
  30.     BaseType_t xHigherPriorityTaskWoken;
  31.     switch (code) {
  32.         case CODE_WIFI_ON_INIT_DONE:
  33.         {
  34.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE", __func__);
  35.             wifi_mgmr_init(&conf);
  36.         }
  37.         break;
  38.         case CODE_WIFI_ON_MGMR_DONE:
  39.         {
  40.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE", __func__);

  41.         }
  42.         break;
  43.         case CODE_WIFI_ON_SCAN_DONE:
  44.         {

  45.             wifi_mgmr_sta_scanlist();
  46.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE SSID numbles:%d", __func__, wifi_mgmr_sta_scanlist_nums_get());

  47.         }
  48.         break;
  49.         case CODE_WIFI_ON_CONNECTED:
  50.         {
  51.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED", __func__);
  52.             void mm_sec_keydump();
  53.             mm_sec_keydump();
  54.         }
  55.         break;
  56.         case CODE_WIFI_ON_GOT_IP:
  57.         {
  58.             ui_load_scr_animation(&guider_ui, &guider_ui.screen_1, guider_ui.screen_1_del, &guider_ui.screen_del, setup_scr_screen_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true, true);
  59.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP", __func__);
  60.         }
  61.         break;
  62.         case CODE_WIFI_ON_DISCONNECT:
  63.         {
  64.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT", __func__);

  65.         }
  66.         break;
  67.         case CODE_WIFI_ON_AP_STARTED:
  68.         {
  69.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED", __func__);
  70.         }
  71.         break;
  72.         case CODE_WIFI_ON_AP_STOPPED:
  73.         {
  74.             LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED", __func__);
  75.         }
  76.         break;
  77.         case CODE_WIFI_ON_AP_STA_ADD:
  78.         {
  79.             LOG_I("[APP] [EVT] [AP] [ADD] %lld", xTaskGetTickCount());
  80.         }
  81.         break;
  82.         case CODE_WIFI_ON_AP_STA_DEL:
  83.         {
  84.             LOG_I("[APP] [EVT] [AP] [DEL] %lld", xTaskGetTickCount());
  85.         }
  86.         break;
  87.         default:
  88.         {
  89.             LOG_I("[APP] [EVT] Unknown code %u ", code);
  90.         }
  91.     }
  92. }
复制代码
调用方法如下:
在主函数中开启线程
tcpip_init(NULL, NULL);
wifi_start_firmware_task();
  1. char * wifi_code;
  2.                     char * wifi_name;
  3.                     wifi_name = lv_textarea_get_text(guider_ui.screen_ta_1);
  4.                     wifi_code = lv_textarea_get_text(guider_ui.screen_ta_2);
  5.                     wifi_connect(wifi_name,wifi_code);
复制代码
这里是从LVGL屏幕的文本框获取WIFI名称和密码。
TCP/IP参考代码与WIFI代码参考同一位置,关键代码如下:
  1. void wifi_test_tcp_client_init(int argc, char **argv)
  2. {
  3.     abort_exec = shell_signal(SHELL_SIGINT, test_close_client);
  4.     printf("tcp client task start ...\r\n");

  5.     char *addr;
  6.     char *port;
  7.     struct sockaddr_in remote_addr;

  8.     if (argc < 3) {
  9.         printf("%s", PING_USAGE);
  10.         return;
  11.     }
  12. printf("111...\r\n");
  13.     /* get address (argv[1] if present) */
  14.     addr = "192.168.31.236";//argv[1];

  15.     /* get port number (argv[2] if present) */
  16.     port = "8888";//argv[2];

  17.     while (1) {
  18.         printf("222...\r\n");
  19.         if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  20.             printf("TCP Client create socket error\r\n");
  21.             return;
  22.         }
  23.         printf("333...\r\n");
  24.         remote_addr.sin_family = AF_INET;
  25.         remote_addr.sin_port = htons(atoi(port));
  26.         remote_addr.sin_addr.s_addr = inet_addr(addr);
  27.         memset(&(remote_addr.sin_zero), 0, sizeof(remote_addr.sin_zero));
  28. printf("444...\r\n");
  29.         printf("Server ip Address : %s:%s\r\n", addr, port);

  30.         if (connect(sock_client, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) != 0) {
  31.             printf("TCP client connect server falied!\r\n");
  32.             closesocket(sock_client);
  33.             return;
  34.         }

  35.         printf("TCP client connect server success!\r\n");
  36.         printf("Press CTRL-C to exit.\r\n");
  37.         total_cnt = 0;
  38.         while (1) {
  39.             if (write(sock_client, send_buf, sizeof(send_buf)) < 0) {
  40.                 printf("write falied!\r\n");
  41.                 break;
  42.             }
  43.             total_cnt += sizeof(send_buf);
  44.             vTaskDelay(500);
  45.         }
  46.         closesocket(sock_client);
  47.         return;
  48.     }
  49. }
复制代码
调用方法如下:
  1. char *ip_addr="192.168.31.62";
  2.                     char *ip_port="333";
  3.                     *ip_port = lv_textarea_get_text(guider_ui.screen_1_ta_1);
  4.                     wifi_test_tcp_server_init(ip_addr,ip_port);
复制代码
在LVGL屏幕中按下按钮调用。
如下为视频,小安派与手机/电脑进行TCP/IP通信测试,并与电脑进行速度测试。
小安派R2测评---WIFI及TCP-IP测试_哔哩哔哩_bilibili
七、总结与开发想法
经过上诉测试,小安派作为智能家居终端十分适合,屏幕刷新及网络传输速度适合,可以读取TF卡。目前时间原因只测试了这么多,后续想法为
1、以小安派为智能终端,控制已知智能家居,连接米家。
2、读取TF卡数据,制作MP3,暂时不具备制作MP4条件(软件解码速度不太够)。
遇到问题:目前网络传输速度仅够传输一些关键数据,无法进行高速图片,视频传输。(个人能力问题,仍在学习),如果解决,可以尝试制作远程终端。
八、遇到问题与建议
1、小安派的屏幕接上开发板后,屏幕与Type-C会发生冲突,这个很多大佬都已经提到了;
2、官方下载器因为(猜测)加密,无法直接进行下载,而VScode下载对于USB转TTL略微麻烦,Type-C无法烧录;
B站视频链接:
小安派R2测评---官方dome演示_哔哩哔哩_bilibili
小安派R2测评---开箱_哔哩哔哩_bilibili
小安派R2测评---LVGL_哔哩哔哩_bilibili
小安派R2测评---WIFI及TCP-IP测试_哔哩哔哩_bilibili
小安派R2测评---LVGL效果_哔哩哔哩_bilibili


回复

使用道具 举报

及辰 | 前天 21:33 | 显示全部楼层
##
编译补充说明,环境,Windows11专业版,VScode
编译报错,make (e=2): 系统找不到指定的文件。
解决办法,找到project.build文件,编辑它,对第75和76行开头加上“#”,意思是注释掉这2行,记得保存.
修改后代码如下

#        cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/edata.bin build/build_out
#        cp $(BL_SDK_BASE)/bsp/board/bl616dk/config/Rx_boot2_m61.bin build/build_out

编译采用make,烧录采用make flash COMX=COM3

如果用例程修改编译代码,需要更改两处
1、打开Makefile,将BOARD_DIR ?= $(NOW_REAL_PATH)/../后面的文件夹名称改成自己新命名的
2、打开flash_prog_cfg.ini,将filedir = ./build/build_out/aaatest_$(CHIPNAME).bin里面的aaatest改成自己新命名的文件夹名

如果需要引入新组件,需要在proj.conf中加入相应的引用

传输速度 1.3 MB/min
一张图片 0.6912MB,每分钟传输1.3/0.6912=1.88,抛去运算,每分钟刷1.8张图,不大够。
黑白图,一张图片 0.0288MB,每分钟传输1.3/0.0288=45.139,抛去运算,每分钟超过24应该可以,可以尝试刷一下。
回复 支持 反对

使用道具 举报

及辰 | 前天 21:35 | 显示全部楼层
代码:通过百度网盘分享的文件:aaatest-1011.rar
链接:https://pan.baidu.com/s/1LyGsjGhVJWtb9_MRSQdgOg?pwd=xo5u
提取码:xo5u
回复 支持 反对

使用道具 举报

大猫的鱼 | 昨天 08:31 | 显示全部楼层
不错不错
回复

使用道具 举报

bzhou830 | 昨天 08:36 | 显示全部楼层
不错不错
选择去发光,而不是被照亮
回复

使用道具 举报

爱笑 | 昨天 08:42 | 显示全部楼层
不错不错!
用心做好保姆工作
回复

使用道具 举报

lazy | 昨天 08:43 | 显示全部楼层
不错不错
回复

使用道具 举报

aramy | 昨天 08:51 | 显示全部楼层
大佬👍!学习
回复 支持 反对

使用道具 举报

大猫的鱼 | 昨天 16:38 | 显示全部楼层
不错不错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则