巨大八爪鱼
巨大八爪鱼
我喜欢做魔塔,更喜欢玩魔塔,尤其是大家用心血做的魔塔。
关注数: 650
粉丝数: 488
发帖数: 21,216
关注贴吧数: 303
88w8801移植到altera fpga使用最笨的办法 88w8801移植到altera fpga使用,最笨的办法,就是把那几个spi引脚全部弄成gpio,然后在nios程序里面直接操作gpio,模拟spi时序 这样连dma都不用了,真简单啊
88W8977和88W8987的引脚图(出自alldatasheet) 88W8977封装:68-pin MQFN - 8 x 8 x 0.85 mm, with 0.4 mm pitch 88W8987封装:68-pin HVQFN - 8 x 8 x 0.85 mm, with 0.4 mm pitch
stm32h743 cmd53 stream模式发数据卡死原因 这是因为,h7的sdmmc里面,DTMODE一共有四种模式,hal库却只能选择其中两种!
88W8801程序移植到STM32H743的SDMMC2(不带DMA) 测试时不要使用杜邦线,一定要把PCB板画出来之后再调试。时钟线长度必须要是数据线长度的两倍。 wifi.h里面,WIFI_CLOCK_FREQ设为1000000(也就是1MHz),WIFI_USEDMA设为0。 wifi_lowlevel.c里面,SDIO全部替换成SDMMC。 WiFi_LowLevel_WriteData(CMD53发送函数)不用改。 只需要改WiFi_LowLevel_ReadData(CMD53接收函数)。 原本STM32F1的程序里面写的是:if (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_RXDAVL) != RESET) 但是STM32H7里面没有RXDAVL位。 RXDAVL(data available)的反义词是RXFIFOE(FIFO empty),我们只需要改成: if (__SDMMC_GET_FLAG(SDMMC2, SDMMC_FLAG_RXFIFOE) == RESET) 就可以了!这个接收函数能完美兼容SDIO 4线模式,以及Stream+Block混合模式(WIFI_RWDATA_ALLOWMULTIBYTE)。
SPI驱动88W8801的核心代码 首先是引脚定义: #define PDN_0 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET) #define PDN_1 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET) #define CS_0 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET) #define CS_1 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET) #define SCK_0 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET) #define SCK_1 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET) #define MISO (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8) == GPIO_PIN_SET) #define MOSI_0 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET) #define MOSI_1 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET) #define INT (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) == GPIO_PIN_SET) 然后实现SPI发送并接收1字节: /* 在SPI总线上发送并接收1字节数据 */ static uint8_t WiFi_LowLevel_SendByte(uint8_t data) { int i; for (i = 0; i < 8; i++) { if (data & 0x80) MOSI_1; else MOSI_0; data <<= 1; SCK_1; if (MISO) data |= 1; SCK_0; } return data; }
我自制的STM32H743ZI的板子,用来研究SDMMC驱动88W8801
有人在STM32F103上成功移植了uip协议栈SPI方式驱动88W8801 SPI速率9M,再高有CRC错误提示了 局域网内ping包延时平均10ms以内,速度够用了
入手5片88W8801 WiFi芯片
必联88W8801模块右上方的6脚小器件是一个滤波器
88W8887 WiFi蓝牙二合一模块支持I2S音频,真是一个先进的模块啊
88W8887 WiFi蓝牙二合一模块的SDIO支持最高150MHz的速率 STM32H7的SDMMC 4位数据线模式最高支持208MHz时钟频率
STM32驱动Marvell 88W8686 WiFi模块代码说明(20180129版) 一、概述 88W8686是Marvell公司2007年推出的一款SDIO Wi-Fi芯片,使用简单的SPI或SDIO协议就可以与单片机连接起来,操作方便,具有创建无密码或带有WEP密码的Ad-Hoc热点的功能,以及连接无密码或带有WEP、WPA/WPA2密码的路由器的功能。不过有一点要注意,安卓手机默认是不能连接Ad-Hoc型的热点的(Win10电脑好像也不行),必须要打补丁才行。也就是说,安卓手机默认是无法连接88W8686创建的热点的,这种情况下最好让安卓手机开一个普通热点(就是路由器建立的那种非Ad-Hoc热点),让Wi-Fi模块自己去连接。 WM-G-MR-9是环旭电子生产的基于Marvell 88W8686的一款Wi-Fi芯片,引脚数远少于88W8686,同样也支持SDIO和SPI接口,使用起来和88W8686是一样的。不过,淘宝网上关于该芯片的搜索结果极少,甚至光是芯片就要20~40元一个,有一家还卖到了175元一个!淘宝网上12块钱左右就可以买到88W8686芯片,但是带该芯片的模块却寥寥无几,带WM-G-MR-9芯片的模块也很贵,要85元,所以建议实际做产品的时候为了降低成本,直接用88W8686贴片芯片,自己画一个PCB板子和单片机连接起来,不要用人家封装好的模块。 Marvell公司近年来还推出了88W8782和88W8801芯片,功能也比88W8686更强大,在淘宝网上无论是裸芯片还是带芯片的模块都要便宜很多,一个模块20块钱就能买到。
【用法】Marvell 88W8801 WiFi模块中CMD_802_11_KEY_MATERIAL命 【用法】Marvell 88W8801 WiFi模块中CMD_802_11_KEY_MATERIAL命令的用法
有民科,那有没有军科?
有没有谁能证明当q=0时,分母2y-p就一定为0?
Win7停止支持后,新装的Win7系统已无法通过Windows Update更新了 看来微软这是要彻底封杀Win7啊,连激活用的服务器,Windows Update服务器都关了。 Win7 SP1升级补丁在官网也下载不了了,说HTTP 404找不到网页。 MSE(Microsoft Security Essentials)也更新不了了。
我正在exynos4412开发板上编译gcc11.2
编译gcc
迅为4412板子上运行gcc10.3编译器成功!
实现工资上缴的代码 #include <tchar.h> #include <Windows.h> #include <CommCtrl.h> #include "resource.h" // 必须启用XP风格 // 否则窗口显示后需要等待几秒钟动画才开始播放 #pragma comment(lib, "comctl32.lib") #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") HWND hwndAnimate; BOOL bPaused = FALSE; int nStep = 0; void CALLBACK TimerProc(HWND hDlg, UINT uMsg, UINT iTimerID, DWORD dwTime) { static int nPos[] = {25, 50, 75, 90, 100}; static int nMoney[] = {1500, 1000, 500, 200, 0}; TCHAR str[20]; if (bPaused) return; _stprintf_s(str, TEXT("剩余%d块"), nMoney[nStep]); SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, nPos[nStep], NULL); SetDlgItemText(hDlg, IDC_TEXT2, str); if (nStep == 3) { bPaused = TRUE; if (MessageBox(hDlg, TEXT("确定要上缴所有钱钱, 不留零花钱吗?"), TEXT("工资上缴"), MB_ICONQUESTION | MB_YESNO) == IDYES) { nStep = 4; bPaused = FALSE; } else EndDialog(hDlg, IDNO); } else if (nStep == 4) { SetDlgItemText(hDlg, IDC_TEXT1, TEXT("上缴完毕! 你是世上最诚实的男人!")); SetDlgItemText(hDlg, IDCANCEL, TEXT("完成")); KillTimer(hDlg, IDT_TIMER1); } else nStep++; } INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { HICON hIcon; int wmId; switch (uMsg) { case WM_COMMAND: wmId = LOWORD(wParam); switch (wmId) { case IDOK: case IDCANCEL: KillTimer(hDlg, IDT_TIMER1); EndDialog(hDlg, wmId); break; } break; case WM_INITDIALOG: hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, 4, NULL); hwndAnimate = GetDlgItem(hDlg, IDC_ANIMATE1); Animate_Open(hwndAnimate, MAKEINTRESOURCE(IDR_AVI1)); SetTimer(hDlg, IDT_TIMER1, 1000, TimerProc); break; } return FALSE; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { InitCommonControls(); DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); return 0; }
为88W8801 WiFi模块的商用而努力!!!!!! 让我们一起奋斗吧!
关于IE11光标变粗的问题 经确认,这个问题是由于电脑里面启用了其他语言的输入法造成的。 原本笔者的电脑里启用了中文、英语、西班牙语和泰语四种语言的输入法。删除两个不用的语言,只保留中文和英文,问题就解决了。
Altera NIOS II驱动RTL8201百兆网口,并运行lwip2.1.2协议栈
กา กา กา กา กา ยาว
88W8887是WiFi和蓝牙二合一的模块 其中,WiFi用的是SDIO接口。 蓝牙用的是UART接口,也就是我们平常所说的串口。
88W8801 WiFi模块创建了热点的情况下,还能同时连接另外一个热点 也就是说,STA和uAP是可以共存的! 如果再配一下那个路由器的路由表,那88W8801创建的热点就能上网了。真厉害啊!
88W8801 WiFi模块的命令ID号 // WiFi命令列表 typedef enum { CMD_802_11_SCAN = 0x0006, // Starts the scan process CMD_MAC_MULTICAST_ADR = 0x0010, // Gets/sets MAC multicast filter table CMD_802_11_ASSOCIATE = 0x0012, // Initiate an association with the AP //CMD_802_11_SET_WEP = 0x0013, // Configures the WEP keys CMD_802_11_DEAUTHENTICATE = 0x0024, // Starts de-authentication process with the AP CMD_MAC_CONTROL = 0x0028, // Controls hardware MAC CMD_802_11_MAC_ADDR = 0x004d, // WLAN MAC address CMD_802_11_KEY_MATERIAL = 0x005e, // Gets/sets key material used to do Tx encryption or Rx decryption CMD_802_11_BG_SCAN_CONFIG = 0x006b, // Gets/sets background scan configuration CMD_802_11_BG_SCAN_QUERY = 0x006c, // Gets background scan results CMD_802_11_SUBSCRIBE_EVENT = 0x0075, // Subscribe to events and set thresholds CMD_TX_PKT_STATS = 0x008d, // Reports the current Tx packet status, CMD_CFG_DATA = 0x008f, // Facilitates downloading of calibration data APCMD_SYS_INFO = 0x00ae, // Returns system information APCMD_SYS_RESET = 0x00af, // Resets the uAP to its initial state APCMD_SYS_CONFIGURE = 0x00b0, // Gets/sets AP configuration parameters APCMD_BSS_START = 0x00b1, // Starts BSS APCMD_BSS_STOP = 0x00b2, // Stops active BSS APCMD_STA_LIST = 0x00b3, // Gets list of client stations currently associated with the AP APCMD_STA_DEAUTH = 0x00b5, // De-authenticates a client station CMD_SUPPLICANT_PMK = 0x00c4, // Configures embedded supplicant information CMD_CHAN_REPORT_REQUEST = 0x00dd // Performs channel load, channel noise histrogram, basic measurement on a given channel } WiFi_CommandList;
88W8801的驱动再复杂,最本质的都是用CMD53读写数据! 这个是用CMD53写数据的代码: /* 发送数据, 自动判断采用哪种传输模式 */ // size为要发送的字节数, bufsize为data缓冲区的大小, bufsize=0时禁用缓冲区检查 int WiFi_LowLevel_WriteData(uint8_t func, uint32_t addr, const void *data, uint32_t size, uint32_t bufsize, uint32_t flags) { int i, err = 0; uint16_t block_num; // 数据块个数 uint32_t cmd53_flags = CMD53_WRITE; #if WIFI_USEDMA LL_DMA_InitTypeDef dma; #else const uint32_t *p = data; #endif if ((uintptr_t)data & 3) { printf("%s: data must be 4-byte aligned!\n", __FUNCTION__); return -2; // 不重试 } if (size == 0) { printf("%s: size cannot be 0!\n", __FUNCTION__); return -2; } block_num = WiFi_LowLevel_GetBlockNum(func, &size, flags); if (bufsize != 0 && bufsize < size) // 只读缓冲区越界不会影响数据传输, 所以这只是一个警告 printf("%s: a buffer of at least %d bytes is required! bufsize=%d\n", __FUNCTION__, size, bufsize); if (flags & WIFI_RWDATA_ADDRINCREMENT) cmd53_flags |= CMD53_INCREMENTING; if (block_num) { sdio_data.TransferMode = SDIO_TRANSFER_MODE_BLOCK; WiFi_LowLevel_SendCMD53(func, addr, block_num, cmd53_flags | CMD53_BLOCKMODE); } else { sdio_data.TransferMode = SDIO_TRANSFER_MODE_STREAM; WiFi_LowLevel_SendCMD53(func, addr, size, cmd53_flags); } WiFi_LowLevel_WaitForResponse(__FUNCTION__); // 必须要等到CMD53收到回应后才能开始发送数据 // 开始发送数据 #if WIFI_USEDMA dma.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; dma.MemoryOrM2MDstAddress = (uint32_t)data; dma.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; dma.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; dma.Mode = LL_DMA_MODE_NORMAL; dma.NbData = size / 4; dma.PeriphOrM2MSrcAddress = (uint32_t)&SDIO->FIFO; dma.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; dma.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; dma.Priority = LL_DMA_PRIORITY_VERYHIGH; LL_DMA_Init(DMA2, LL_DMA_CHANNEL_4, &dma); LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_4); #endif sdio_data.DataLength = size; sdio_data.DPSM = SDIO_DPSM_ENABLE; sdio_data.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; SDIO_ConfigData(SDIO, &sdio_data); #if !WIFI_USEDMA while (size > 0) { size -= 4; SDIO_WriteFIFO(SDIO, (uint32_t *)p); // 向FIFO送入4字节数据 p++; while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXFIFOF) != RESET); // 如果FIFO已满则等待 // 如果出现错误, 则退出循环 err += WiFi_LowLevel_CheckError(__FUNCTION__); if (err) break; } #endif // 等待发送完毕 i = 0; while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DATAEND) == RESET) { err += WiFi_LowLevel_CheckError(__FUNCTION__); if (err) break; i++; if (i == CMD53_TIMEOUT) { printf("%s: timeout!\n", __FUNCTION__); // 用于跳出TXACT始终不清零, 也没有错误标志位置位的情况 err++; break; } } sdio_data.DPSM = SDIO_DPSM_DISABLE; SDIO_ConfigData(SDIO, &sdio_data); #if WIFI_USEDMA LL_DMA_ClearFlag_GI4(DMA2); // 清除DMA传输完成标志位 LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_4); // 关闭DMA #endif // 清除相关标志位 __SDIO_CLEAR_FLAG(SDIO, SDIO_FLAG_DATAEND | SDIO_FLAG_DBCKEND); err += WiFi_LowLevel_CheckError(__FUNCTION__); if (err != 0) return -1; return 0; }
发了2个多G的数据了,88W8801 WiFi模块还没挂,真好用啊!
88W8801 WiFi模块的固件是怎样下载的呢,让我们来看一看 所谓的固件,就是一个250KB的超大数组:/* 固件下载 */ // WiFi模块必须要有固件才能正常工作, 固件是由Marvell公司(WiFi模块的制造商)开发的 // 固件内容是保存在STM32单片机的Flash里面的, Flash里面保存的内容在断电时不会丢失 // 通电时(或单片机复位后), 单片机把保存在Flash里面的固件通过SPI或SDIO接口发送给WiFi模块 // 存到WiFi模块的SRAM(内存)里面运行, SRAM里面的内容一断电或复位就会丢失 // 所以每次断电或复位后都要重新下载固件 void WiFi_DownloadFirmware(void) { const uint8_t *data; int i, ret; uint16_t curr, retry; uint32_t len; if (WiFi_GetFirmwareStatus() == WIFI_FIRMWARESTATUS_OK) { // PDN引脚没有正确连接到单片机上, 单片机复位时WiFi模块就无法跟着复位 // 所以这个时候不需要重新下载固件 // WiFi模块原有的状态不变 (比如已连上的热点, 已发送但未接收回应的命令) // 这个时候继续运行下去, 很可能会出错 printf("%s: Reset signal has no effect!\n", __FUNCTION__); printf("Please make sure PDN pin is connected to the MCU!\n"); return; } // 下载固件 data = WIFI_FIRMWARE_ADDR; // 该地址必须是4字节对齐的, 否则将会引起传输错误 len = WIFI_FIRMWARE_SIZE; while (len) { // 获取本次应下载的字节数 // 每次可以发送n>=curr字节的数据, 只能用一个CMD53命令发送, WiFi模块只认前curr字节的数据 // 88W8801不会出现curr=0的情况, 所以这里不需要while语句 curr = WiFi_LowLevel_ReadReg(1, WIFI_SQREADBASEADDR0) | (WiFi_LowLevel_ReadReg(1, WIFI_SQREADBASEADDR1) << 8); #if WIFI_DISPLAY_FIRMWARE_DNLD printf("Required: %d bytes, Remaining: %d bytes\n", curr, len); #endif // 发送固件数据 i = 0; do { ret = WiFi_LowLevel_WriteData(1, wifi_port, data, curr, 0, WIFI_RWDATA_ALLOWMULTIBYTE); if (ret == -2) break; // 参数有误 ret = WiFi_Wait(WIFI_INTSTATUS_DNLD, 100); // 等待响应 retry = WiFi_LowLevel_ReadReg(1, WIFI_SQREADBASEADDR0); if (retry & 1) { ret = -1; // 如果寄存器的值为奇数, 说明模块收到的固件内容有误, 需要重传 retry |= WiFi_LowLevel_ReadReg(1, WIFI_SQREADBASEADDR1) << 8; printf("%s: Data were not recognized! curr=%d, retry=%d, remaining=%d\n", __FUNCTION__, curr, retry, len); } i++; } while (ret == -1 && i < WIFI_LOWLEVEL_MAXRETRY); // 如果成功就跳出循环, 失败就重传 if (ret != 0) { printf("Failed to download firmware!\n"); abort(); } len -= curr; data += curr; } // 等待Firmware启动 while (WiFi_GetFirmwareStatus() != WIFI_FIRMWARESTATUS_OK); printf("Firmware is successfully downloaded!\n"); } /* 获取固件状态 */ uint16_t WiFi_GetFirmwareStatus(void) { return WiFi_LowLevel_ReadReg(1, WIFI_SCRATCH0_0) | (WiFi_LowLevel_ReadReg(1, WIFI_SCRATCH0_1) << 8); }
88W8801创建热点的代码 /* 创建热点 */ void WiFi_StartMicroAP(const WiFi_AccessPoint *ap, uint32_t flags, WiFi_Callback callback, void *arg) { uint8_t *end; WiFi_ArgBase *p; WiFi_APCmd_SysConfigure *cmd; MrvlIETypes_ApBCast_SSID_Ctrl_t *apbcast; MrvlIETypes_SSIDParamSet_t *ssid; MrvlIETypes_WPA_Passphrase_t *wpa_passphrase; MrvlIETypes_EncryptionProtocol_t *encryption; MrvlIETypes_AKMP_t *akmp; MrvlIETypes_PTK_Cipher_t *ptk_cipher; MrvlIETypes_GTK_Cipher_t *gtk_cipher; if (ap->sec_type == WIFI_SECURITYTYPE_WEP) { printf("%s: WEP is not supported in AP mode!\n", __FUNCTION__); if (callback != NULL) callback(arg, NULL, WIFI_STATUS_INVALID); return; } p = WiFi_AllocateArgument(sizeof(WiFi_ArgBase), __FUNCTION__, ap->bss, callback, arg); if (p == NULL) return; cmd = (WiFi_APCmd_SysConfigure *)WiFi_GetSubCommandBuffer((void **)&p); if (cmd == NULL) return; cmd->action = WIFI_ACT_SET; apbcast = (MrvlIETypes_ApBCast_SSID_Ctrl_t *)(cmd + 1); apbcast->header.type = WIFI_MRVLIETYPES_APBCASTSSIDCTRL; apbcast->header.length = TLV_PAYLOADLEN(*apbcast); if (flags & WIFI_MICROAP_BROADCASTSSID) apbcast->bcast_ssid_ctl = 1; else apbcast->bcast_ssid_ctl = 0; end = TLV_NEXT(apbcast); if ((flags & WIFI_MICROAP_USEDEFAULTSSID) == 0) { ssid = (MrvlIETypes_SSIDParamSet_t *)end; ssid->header.type = WIFI_MRVLIETYPES_SSIDPARAMSET; ssid->header.length = strlen(ap->ssid); memcpy(ssid->ssid, ap->ssid, ssid->header.length); end = TLV_NEXT(ssid); } switch (ap->sec_type) { case WIFI_SECURITYTYPE_WPA: case WIFI_SECURITYTYPE_WPA2: wpa_passphrase = (MrvlIETypes_WPA_Passphrase_t *)end; wpa_passphrase->header.type = WIFI_MRVLIETYPES_WPAPASSPHRASE; wpa_passphrase->header.length = strlen(ap->password.wpa); memcpy(wpa_passphrase->passphrase, ap->password.wpa, wpa_passphrase->header.length); encryption = (MrvlIETypes_EncryptionProtocol_t *)TLV_NEXT(wpa_passphrase); encryption->header.type = WIFI_MRVLIETYPES_ENCRYPTIONPROTOCOL; encryption->header.length = TLV_PAYLOADLEN(*encryption); if (ap->sec_type == WIFI_SECURITYTYPE_WPA) encryption->protocol = WIFI_ENCRYPTIONPROTOCOL_WPA; else if (ap->sec_type == WIFI_SECURITYTYPE_WPA2) encryption->protocol = WIFI_ENCRYPTIONPROTOCOL_WPA2; akmp = (MrvlIETypes_AKMP_t *)TLV_NEXT(encryption); akmp->header.type = WIFI_MRVLIETYPES_AKMP; akmp->header.length = TLV_PAYLOADLEN(*akmp); akmp->key_mgmt = WIFI_KEY_MGMT_PSK; akmp->operation = 0; ptk_cipher = (MrvlIETypes_PTK_Cipher_t *)akmp; ptk_cipher->header.type = WIFI_MRVLIETYPES_PTKCIPHER; ptk_cipher->header.length = TLV_PAYLOADLEN(*ptk_cipher); ptk_cipher->protocol = encryption->protocol; ptk_cipher->pairwise_cipher = WIFI_WPA_CIPHER_CCMP; ptk_cipher->reserved = 0; gtk_cipher = (MrvlIETypes_GTK_Cipher_t *)TLV_NEXT(ptk_cipher); gtk_cipher->header.type = WIFI_MRVLIETYPES_GTKCIPHER; gtk_cipher->header.length = TLV_PAYLOADLEN(*gtk_cipher); gtk_cipher->groupwise_cipher = WIFI_WPA_CIPHER_CCMP; gtk_cipher->reserved = 0; end = TLV_NEXT(gtk_cipher); break; default: break; } WiFi_SetCommandHeader(&cmd->header, ap->bss, APCMD_SYS_CONFIGURE, end - (uint8_t *)cmd, 1); WiFi_SendCommand(WiFi_StartMicroAP_Callback, p); } static void WiFi_StartMicroAP_Callback(void *arg, void *data, WiFi_Status status) { uint16_t code; WiFi_ArgBase *p = arg; WiFi_CommandHeader *cmd; if (status != WIFI_STATUS_OK) goto end; code = WiFi_GetCommandCode(data); if (code == APCMD_BSS_START) goto end; cmd = WiFi_GetSubCommandBuffer((void **)&p); if (cmd == NULL) return; WiFi_SetCommandHeader(cmd, p->bss, APCMD_BSS_START, sizeof(WiFi_CommandHeader), 1); WiFi_SendCommand(WiFi_StartMicroAP_Callback, p); return; end: WiFi_FreeArgument((void **)&p, data, status); }
【分享】C语言计算任意CRC多项式的代码 #define POLYNOMIAL_CRC7 0x89ul #define POLYNOMIAL_CRC16 0x11021ul /* 计算CRC7校验码 */ static uint8_t WiFi_LowLevel_CalcCRC7(const void *data, int len) { const uint8_t *p = data; int i, j; uint16_t temp = 0; if (len != 0) temp = p[0] << 8; for (i = 1; i <= len; i++) { if (i != len) temp |= p[i]; for (j = 0; j < 8; j++) { if (temp & 0x8000) temp ^= POLYNOMIAL_CRC7 << 8; temp <<= 1; } } return temp >> 9; } /* 计算CRC16校验码 */ static uint16_t WiFi_LowLevel_CalcCRC16(const void *data, int len) { const uint8_t *p = data; int i, j; uint32_t temp = 0; if (len & 1) { printf("%s: data size %d is odd!\n", __FUNCTION__, len); len--; // 不允许出现奇数长度 } if (len != 0) temp = (p[0] << 24) | (p[1] << 16); // 填充前二分之一 if (len > 2) temp |= p[2] << 8; // 填充到四分之三 for (i = 3; i <= len + 2; i++) { if (i < len) temp |= p[i]; // 每次都填充最后四分之一的空间 // 从左数第0~7位计算到左数第16~23位 for (j = 0; j < 8; j++) { if (temp & 0x80000000) temp ^= POLYNOMIAL_CRC16 << 15; temp <<= 1; } } return temp >> 16; }
测试STM32驱动88W8801 WiFi模块
Marvell 88W8801 WiFi模块创建或连接热点,并使用lwip2.1.2建立h Marvell 88W8801 WiFi模块创建或连接热点,并使用lwip2.1.2建立http服务器(20200208版) 本程序所用的单片机型号为:STM32F103RE或STM32F407VE 复位引脚(PDN)应连接到STM32F1的PA15引脚或STM32F4的PD14引脚。不连接PDN引脚将导致固件无法下载!如果模块上有PDN和RESET两个引脚,只需要连接PDN引脚。因为模块上的RESET引脚是悬空的,根本就没有连到芯片上 晶振用的是8MHz,请注意检查自己的开发板,看看晶振是不是8MHz。如果是12MHz,在标准库程序中请修改system_stm32f10x.c或system_stm32f4xx.c文件,在HAL库程序中请修改common.c的clock_init函数。在F1单片机上是把PLL的倍频系数由9改成6(8×9=12×6),并在工程属性中定义HSE_VALUE=12000000 程序支持连接无密码的热点以及WEP、WPA-PSK和WPA2-PSK认证类型的热点,加密方式支持TKIP和AES。WEP加密类型仅支持添加一个密钥 程序还支持创建无密码的热点以及WPA-PSK和WPA2-PSK认证类型的热点,此时板子的IP地址默认为192.168.20.1(IPv4)和fd20::1(IPv6) 连接热点属于STA模式,创建热点属于μAP模式。这两个模式可以同时启用。如果在LWIP上配置了IP_FORWARD选项,并在STA模式所连的路由器上配置好路由表,那么连接了μAP热点的设备就可以上网,也就是“电脑--->88W8801--->路由器--->Internet”的模式(创建可以上网的热点的方法) 如果热点名称包含中文,请注意中文字符的编码。比如笔者的中文名热点"一个WiFi"是用的UTF-8编码,程序里面应该写成"\xe4\xb8\x80\xe4\xb8\xaaWIFI"。也可以用记事本将c源文件以UTF-8编码格式保存,然后直接写"一个WiFi"这个字符串 另外,88W8801不支持Ad-Hoc点对点模式(88W8686支持) 用Keil5编写程序的时候,工程文件夹路径最好不要出现中文哦!不然代码提示可能会有问题 程序是裸机运行的,不带操作系统,运行最新的lwip-2.1.2协议栈 lwip2.1版本的压缩包(lwip-2.1.0.zip)中的src/netif文件夹下没有ethernetif.c了,那个文件是被移动到contrib-2.1.0.zip的examples/ethernetif文件夹下去了 sd8801_uapsta.c是WiFi模块的固件,上电运行时必须由单片机发送给WiFi模块运行 该固件数据非常大,为了节约程序编译下载的时间,可以运行flash_saver程序将这些数据保存到Flash固定区域(要求芯片Flash容量至少为384KB) 然后根据串口提示,修改WiFi.h中WIFI_FIRMWAREAREA_ADDR的值(取消注释) 这样就可以移除sd8801_uapsta.c文件,大幅度降低程序烧写时间了 如果SDIO程序在固件下载完成后频繁出现CRC校验错误以及超时(timeout)的错误,可以将SDIO改为1位模式,并考虑将WIFI_CLOCK_FREQ的值降低,降速运行 如果SPI程序频繁出现missed an interrupt的错误,则说明PC9内部的下拉电阻不起作用,建议在PC9引脚上外接一个阻值较小的下拉电阻。如果还是不行,则在wifi.h中将WIFI_LOWLEVEL_NOINTPIN设为1即可解决问题(也就是将中断方式改为轮询方式,这样会占用较多CPU资源) 本程序也支持88W8782芯片,但需要将固件sd8801_uapsta.c替换成8782的内容,然后把WiFi.h中的数据发送通道数WIFI_DATAPORTS_TX_NUM由11改为15
2020年了 RT
申请恢复被误删内容,词条:一元四次方程 本人当时点击的是编辑词条“解不含三次项的四次方程"这一节的内容,提交后词条通过了,但发现其他小节的内容都没有了。故申请恢复这部分内容。 提交时间:2019-09-20 22:06:40
我dark A都通关了
STM32F103C8单片机操作USB寄存器实现USB设备的枚举过程 STM32F103C8 USB USB reset! // STM32 USB外设本身的复位 (先清除PDWN位, 再清除FRES位), 此时设备为Powered状态 USB reset! // 主机让USB设备复位, 设备由Powered状态转变为Default状态 0+8 // 端点0收到8字节数据 (Setup stage: hostOUT+hostData+deviceACK) 8006000100004000 // 主机请求设备描述符, 请求的最大数据长度为0x40=64字节 0-18 // 端点0发出18字节的设备描述符数据 (Data stage: hIN+dData+hACK) 0+0 // 主机确认收到数据 (Status stage: hOUT+hDATA+dACK) USB reset! // 主机再次让USB设备复位 0+8 0005130000000000 // 主机给USB设备分配设备地址0x13, 不请求数据 (Setup stage: hOUT+hData+dACK) DADDR_13 0-0 // 设备确认收到数据, 并修改设备地址为0x13 (Status stage: hIN+dData+hACK), 设备由Default状态转变为Address状态 0+8 8006000100001200 // 主机再次请求设备描述符, 最大数据长度为0x12=18字节 0-18 // 设备通过端点0发送18字节的设备描述符 0+0 // 主机确认收到数据 0+8 800600020000FF00 // 主机请求配置描述符 0-32 // 设备发送32字节的配置描述符,顺带将接口描述符和端点描述符也发送给主机(USB规范要求) 0+0 // 主机确认 0+8 800600030000FF00 // 主机请求字符串的语言列表 0-4 // 设备告诉主机, 设备只支持0x0409 English (United States)这一种语言 0+0 0+8 800603030904FF00 // 主机请求3号字符串用0x0409这个语言(英语)写的内容 0-40 // 设备发送字符串内容 0+0 0+8 8006000600000A00 // 主机请求Device qualifier描述符, 但由于USB规范规定USB全速设备不支持这个描述符, 所以直接STALL, 向主机报告错误 0+8 8006000100001200 // 主机再次请求18字节的设备描述符 0-18 0+0 0+8 8006000200000900 // 主机请求配置描述符, 但这次只允许设备发送9字节的内容 0-9 // 配置描述符共有32字节, 设备只发送前9字节给主机, 发送的内容不作任何修改(wTotalLength=32, 绝对不允许改成9) 0+0 // 主机确认收到数据 0+8 8006000200002000 // 主机再次请求配置描述符, 最大长度改成了0x20=32字节 0-32 // 设备发送了完整的配置描述符 0+0 0+8 8006000300000200 // 主机请求字符串语言列表, 但只允许设备发送2字节的内容 (实际上就是要获取语言列表的长度) 0-2 // 语言列表共有4字节, 设备只发送前两字节, 内容中的bLength=4保持不变 0+0 0+8 8006000300000400 // 主机请求字符串语言列表, 最大长度改成了4字节 0-4 // 设备发送了完整的语言列表 0+0 0+8 8006030309040200 // 主机请求3号字符串的英语内容的长度 0-2 0+0 0+8 8006030309042800 // 主机请求3号字符串的英语内容 0-40 0+0 0+8 0009010000000000 // 应用1号配置, 设备现在由Address状态转变为最终的Configured状态 CFG1 0-0 0+8 A1FE000000000100 // 后面的代码还没写, 因为调用了两次dump_data, 所以数据内容输出了两次 A1FE000000000100 // A1表示: 方向为从设备到主机, 获取大容量存储Class的接口(Interface)信息 0+8 A1FE000000000100 A1FE000000000100 0+8 A1FE000000000100 A1FE000000000100 1+31 // 端点1收到了31字节的数据 5553424310109C112400000080000612000000240000000000000000000000 USB reset! // 端点没有回应, 所以主机认为出错了, 因此就发送了复位请求 USB reset! 0+8 8006000100004000 0-18 0+0 0+8 0005140000000000 DADDR_14 0-0 0+8 8006000100001200 0-18 0+0 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 0+8 0005160000000000 DADDR_16 0-0 0+8 8006000100001200 0-18 0+0 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 0+8 0005170000000000 DADDR_17 0-0 0+8 8006000100001200 0-18 0+0 0+8 800600020000FF00 0-32 0+0 0+8 0009010000000000 CFG1 0-0 1+31 555342431010AF0D2400000080000612000000240000000000000000000000 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 0+8 0005180000000000 DADDR_18 0-0 0+8 8006000100001200 0-18 0+0 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 USB reset! USB reset! 0+8 8006000100004000 0-18 0+0 0+8 00051A0000000000 DADDR_1A 0-0 0+8 8006000100001200 0-18 0+0 0+8 800600020000FF00 0-32 0+0
Marvell 88W8686 WiFi模块(WM-G-MR-09)创建或连接热点,并使用 Marvell 88W8686 WiFi模块(WM-G-MR-09)创建或连接热点,并使用lwip2.0.3建立http服务器
Marvell 88W8801 WiFi模块连接路由器,并使用lwip2.0.3建立http Marvell 88W8801 WiFi模块连接路由器,并使用lwip2.0.3建立http服务器
是不是所有的有理分式积分后都可以用对数函数和反三角函数表示呢 换句话说,是否存在无法用初等函数表示的有理函数积分?
dy/dx=3y/x+3是不是齐次微分方程? 该方程里面有常数项,但符合dy/dx=f(y/x)形式
神秘魔塔1.0~2.1正式版
【下载地址】Rxdata文件查看器Beta1测试版 RPGDataViewerV1.0Beta1:http://tieba.baidu.com/mo/q/checkurl?url=https%3A%2F%2Fpan.baidu.com%2Fs%2F1qZAmuyK&urlrefer=04b56d1464f804e9181eec71b3070e01
您的帐号疑似被盗,验证密保后继续
【预告】rxdata文件查看器
金山快盘现在改成个人视频了 估计没人敢用吧
坏消息来了,现在Win7没法选择性安装更新了,也没办法查看要安装的是哪些更新了,微软太狠了!
坏消息来了,现在Win7没法选择性安装更新了,也没办法查看要安装的是哪些更新了,微软太狠了!各位不要天真的以为点了那个Install now按钮后只是安装Windows Update这个组件的更新。 实际上里面包含了288个更新,其中还有臭名昭著的KB3035583(也就是那个讨厌的Windows10更新图标),以及被微软拍扁了的IE11浏览器。以前还可以把勾去掉,不安装这几个更新,现在是门都没有,你看都看不到装了哪些东西!关机安装需要至少两个小时!再次开机还要自动重启n次,最后进入桌面前还来了一个全屏的深蓝色背景的醒目的Win10升级文字: Sorry to interrupt(抱歉打扰一下) We recommend you upgrade to Window 10, which have been installed on up to 300 million devices...... (Win10里面不再称computer了,改称device了。。。) 幸好左下角还有取消的链接,不然真JJ了。。。 今天开机后我是气急败坏,IE9被强制拍扁成IE11了不说,右下角Win10的图标也给冒出来了。而且电脑还爆卡!QQ打开了几次都无响应。还有就是那个QQ的图标也被腾讯拍扁了,这二向箔的威力太大了!昨天我真的太天真了,以为真的只是更新一下Windows Update,谁知道呢,里面的水原来这么深 所以没办法了,现在只有彻底把Windows Update给关闭了。因为现在IE11和Win10补丁前面的勾已经无法去掉了,只要安装更新这两个肯定是会重新安装上的。 另外这里顺便吐槽一下IE10和11。这两个浏览器都是2013年发布的,也就是2012年扁平化开始流行之后的那一年。这两个家伙不仅把上面的网页选项卡给拍扁了,还TM把滚动条和网页上的各种文本框、单/复选框、按钮等控件全拍成了Win8的样子,在Win7下看着真的非常恶心! 因此,我是宁愿放弃IE10、11所支持的HTML5的一些新特性,也不愿升级。现在虽然微软的官网上把Win7的IE9的安装包给彻底删掉了,但是在国内的网站上还是可以下载到的。
VS2012生成的Release版本的程序中竟然含有工程文件的路径! http://tieba.baidu.com/mo/q/checkurl?url=https%3A%2F%2Fzh.arslanbar.net%2FFiles%2FTopicImages%2F2016-6%2F1_2016-6-20_073615_5085483218.png&urlrefer=b647ff596b2b5171bf74c6ef631f1b95
为什么errno无法检测出pow函数的错误? errno = 0; printf("%ld\n", pow((double)25, (double)185)); printf("errno=%d\n", errno); if (errno) { puts("failed"); return 1; } 明显25的185次方算不出来,但为什么errno还是0?
有谁还记得有这么个吧?
表示好久都没碰过魔塔了
模糊的win10
【原创】模拟操作系统运行应用程序的C程序 【OS.c】 #include <stdio.h> char memory[256]; // 假定这个就是“操作系统”的一块内存 int main() { char *pStr; int size, n; // 将要运行的程序读入“内存” FILE *fp = fopen("app.hrb", "r"); fseek(fp, 0, SEEK_END); size = ftell(fp) - 1; // size = 文件大小 - 1 fseek(fp, 1, SEEK_SET); // 必须跳过文件中的第一个字节 fread(memory, size, 1, fp); // 从第二个字节开始读取,一直到文件结束 fclose(fp); // 运行“程序”, 并获取“程序”向“操作系统”返回的值 n = ((int (*)())memory)(); pStr = memory + n; puts(pStr); // 输出程序中的字符串 return 0; }
【程序】Invader Windows版
【原创汇编语言程序】在软盘启动画面上用循环显示”0123456789“
【原创程序】用php语言读取rxdata文件 本例以jqs的作品《明静的幻想》中的MapInfos.rxdata文件为例,读取该文件里保存的所有地图的名称并显示出来。 先看运行效果,再看代码:
今天刚好发射10周年 rt
【预告】Flash魔塔样板用的魔塔地图编辑器(高仿RMXP)
首页
1
2
3
4
下一页