完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在笔者所用的开发板上,Wi-Fi模块的VCC不是直接接到电源上的,而是串联了一个场效应管,当PA15为低电平时Wi-Fi模块通电。 【Keil4工程截图】 【程序运行结果】 // 定义与单片机寄存器操作相关的函数, 方便在不同平台间移植 #include #include #include "common.h" #include "WiFi.h" #define CS_0 GPIO_WriteBit(GPIOC, GPIO_Pin_11, Bit_RESET) #define CS_1 GPIO_WriteBit(GPIOC, GPIO_Pin_11, Bit_SET) #define SCK_0 GPIO_WriteBit(GPIOC, GPIO_Pin_12, Bit_RESET) #define SCK_1 GPIO_WriteBit(GPIOC, GPIO_Pin_12, Bit_SET) #define MISO (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8) == Bit_SET) #define MOSI_0 GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET) #define MOSI_1 GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET) #define CMD52_WRITE _BV(31) #define CMD52_READAFTERWRITE _BV(27) #define CMD53_WRITE _BV(31) #define CMD53_BLOCKMODE _BV(27) #define CMD53_INCREMENTING _BV(26) static uint8_t WiFi_LowLevel_CalcCRC7(const void *data, uint16_t len); static void WiFi_LowLevel_GPIOInit(void); static void WiFi_LowLevel_ReceiveResponse(uint8_t *resp, uint8_t resp_len); static void WiFi_LowLevel_SDIOInit(void); static void WiFi_LowLevel_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags, uint8_t *resp, uint8_t resp_len); static void WiFi_LowLevel_Send(uint8_t *data, uint16_t len); static uint8_t WiFi_LowLevel_SendByte(uint8_t data); static void WiFi_LowLevel_SendCommand(uint8_t index, uint32_t argument, uint8_t *resp, uint8_t resp_len); static uint8_t sdio_func_num = 0; // 功能区总数 (0号功能区除外) /* 计算CRC7校验码 */ static uint8_t WiFi_LowLevel_CalcCRC7(const void *data, uint16_t len) { const uint8_t *p = data; const uint8_t polynomial = 0x89; uint8_t j; uint16_t temp = p[0] << 8; uint16_t i; for (i = 1; i <= len; i++) { if (i != len) temp |= p; for (j = 0; j < 8; j++) { if (temp & 0x8000) temp ^= polynomial << 8; temp <<= 1; } } return temp >> 9; } /* 获取WiFi模块支持SDIO功能区个数 (0号功能区除外) */ uint8_t WiFi_LowLevel_GetFunctionNum(void) { return sdio_func_num; } /* 判断是否触发了网卡中断 */ uint8_t WiFi_LowLevel_GetITStatus(uint8_t clear) { if (EXTI_GetFlagStatus(EXTI_Line9) == SET) { if (clear) EXTI_ClearFlag(EXTI_Line9); return 1; } else return 0; } /* 初始化WiFi模块有关的所有GPIO引脚 */ static void WiFi_LowLevel_GPIOInit(void) { EXTI_InitTypeDef exti; GPIO_InitTypeDef gpio; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // 使Wi-Fi模块复位信号(PDN)有效 gpio.GPIO_Mode = GPIO_Mode_OUT; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Pin = GPIO_Pin_14; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio.GPIO_Speed = GPIO_Low_Speed; GPIO_Init(GPIOD, &gpio); GPIO_WriteBit(GPIOD, GPIO_Pin_14, Bit_RESET); // PA15为MOS管控制的Wi-Fi模块电源开关, 低电平时Wi-Fi模块通电 gpio.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOA, &gpio); GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET); // 撤销Wi-Fi模块的复位信号 delay(10); // 延时一段时间, 使WiFi模块能够正确复位 GPIO_WriteBit(GPIOD, GPIO_Pin_14, Bit_SET); // SDIO相关引脚 // PC8: MISO, 设为浮空输入 gpio.GPIO_Mode = GPIO_Mode_IN; gpio.GPIO_Pin = GPIO_Pin_8; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &gpio); // PC9: INT, 设为带上拉电阻的输入 gpio.GPIO_Mode = GPIO_Mode_IN; gpio.GPIO_Pin = GPIO_Pin_9; gpio.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &gpio); // PC11: CS, PC12: SCK, 设为推挽输出 CS_1; gpio.GPIO_Mode = GPIO_Mode_OUT; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio.GPIO_Speed = GPIO_High_Speed; GPIO_Init(GPIOC, &gpio); // PD2: MOSI, 设为推挽输出 gpio.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOD, &gpio); // 配置外部中断 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource9); exti.EXTI_Line = EXTI_Line9; exti.EXTI_LineCmd = ENABLE; exti.EXTI_Mode = EXTI_Mode_Interrupt; exti.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_Init(&exti); } void WiFi_LowLevel_Init(void) { WiFi_LowLevel_GPIOInit(); WiFi_LowLevel_SDIOInit(); } /* 读SDIO寄存器 */ uint8_t WiFi_LowLevel_ReadReg(uint8_t func, uint32_t addr) { uint8_t resp[2]; WiFi_LowLevel_SendCMD52(func, addr, 0, 0, resp, sizeof(resp)); return resp[1]; } /* 接收指定长度的SDIO命令回应 */ // 7.3.2.1 Format R1 // 7.5.1.1 Host Command to Card Response - Card is ready // 7.5.4 Timing Values static void WiFi_LowLevel_ReceiveResponse(uint8_t *resp, uint8_t resp_len) { uint8_t i, temp; // 等待回应期间 (NCR), MISO始终为高电平 // Modified R1回应的最高位为0, 当接收到的字节的最高位为0时退出循环 do { temp = WiFi_LowLevel_SendByte(0xff); } while (temp & 0x80); resp[0] = temp; for (i = 1; i < resp_len; i++) resp = WiFi_LowLevel_SendByte(0xff); } static void WiFi_LowLevel_SDIOInit(void) { uint8_t resp[5]; // 延时可防止CMD5重发 (6.4 Power Scheme) delay(100); WiFi_LowLevel_SendByte(0xff); // 在CS=1的情况下发送8个空时钟 /* 切换到SPI模式 (CMD0: Used to change from SD to SPI mode) */ WiFi_LowLevel_SendCommand(0, 0, resp, 1); printf("CMD0, R1_%02Xn", resp[0]); /* 发送CMD5: IO_SEND_OP_COND */ WiFi_LowLevel_SendCommand(5, 0, resp, sizeof(resp)); printf("CMD5, R1_%02X, RESP1_%02x%02x%02x%02xn", resp[0], resp[1], resp[2], resp[3], resp[4]); /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */ WiFi_LowLevel_SendCommand(5, 0x300000, resp, sizeof(resp)); printf("CMD5, R1_%02X, RESP1_%02x%02x%02x%02xn", resp[0], resp[1], resp[2], resp[3], resp[4]); if (resp[1] & _BV(7)) { // Card is ready to operate after initialization sdio_func_num = (resp[1] >> 4) & 7; printf("Number of I/O Functions: %dn", sdio_func_num); printf("Memory Present: %dn", (resp[1] & _BV(3)) != 0); } // SPI模式不支持CMD3和CMD7, 所以不需要发送这两个命令 } static void WiFi_LowLevel_Send(uint8_t *data, uint16_t len) { uint16_t i; for (i = 0; i < len; i++) data = WiFi_LowLevel_SendByte(data); } static uint8_t WiFi_LowLevel_SendByte(uint8_t data) { uint8_t i; uint8_t recved = 0; for (i = 0; i < 8; i++) { if (data & 0x80) MOSI_1; else MOSI_0; data <<= 1; SCK_1; recved <<= 1; if (MISO) recved |= 1; SCK_0; } return recved; } static void WiFi_LowLevel_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags, uint8_t *resp, uint8_t resp_len) { uint32_t arg = (func << 28) | (addr << 9) | data | flags; WiFi_LowLevel_SendCommand(52, arg, resp, resp_len); } static void WiFi_LowLevel_SendCommand(uint8_t index, uint32_t argument, uint8_t *resp, uint8_t resp_len) { uint8_t crc; uint8_t data[6]; data[0] = index | 0x40; // 最高位为起始位, 始终为0, SD卡从起始位开始接收命令 data[1] = argument >> 24; data[2] = argument >> 16; data[3] = argument >> 8; data[4] = argument; crc = WiFi_LowLevel_CalcCRC7(data, 5); data[5] = (crc << 1) | 1; CS_0; WiFi_LowLevel_Send(data, sizeof(data)); WiFi_LowLevel_ReceiveResponse(resp, resp_len); CS_1; } /* 写寄存器, 返回写入后寄存器的实际内容 */ uint8_t WiFi_LowLevel_WriteReg(uint8_t func, uint32_t addr, uint8_t value) { uint8_t resp[2]; WiFi_LowLevel_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE, resp, sizeof(resp)); return resp[1]; } |
||
|
||
只有小组成员才能发言,加入小组>>
3043 浏览 9 评论
2746 浏览 16 评论
3256 浏览 1 评论
8584 浏览 16 评论
3844 浏览 18 评论
9446浏览 3评论
724浏览 3评论
371浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
364浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2095浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-6-25 15:06 , Processed in 0.747975 second(s), Total 48, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191