Windows 环境下解决fastdfs_client安装报错的问题

最近做的Django项目中需要存储图片文件,为了解决图片存储的问题,所以引入了FastDFS,主要是以下两个问题

  • 存储相同名称的不同文件
  • 存储不同名称的相同文件

简单说一下FastDFS

FastDFS 是用 c 语言编写的一款开源的分布式文件系统。

FastDFS 为互联网量身定制, 充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

FastDFS 架构包括 Tracker server 和 Storage server。客户端(client)请求 Tracker server 进行文 件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。

开发环境

1.docker容器中运行单节点的跟踪器(tracker)和存储节点(storage)
2.在windows10系统,python虚拟环境下安装 fastdfs_client 进行开发调试(python解释器版本:3.6.5)
3.使用的IDE:pycharm

安装fastdfs_client报错

pip install fdfs_client
报错信息

解决办法

1.下载fdfs_client包
(下载地址:http://down.51cto.com/data/2448725)
解压之后直接将fdfs_client文件夹copy到python解释器的 /lib 目录下
解压得到的文件夹:
fdfs
copy到python解释器的 /lib 目录下
fdfs_client
2. 修改fdfs_client/storage_client.py文件,将第12行删除或注释(否则,使用时会报错ImportError: No module named sendfile)
# from fdfs_client.sendfile import *
3.安装 mutagen 和 requests
pip install mutagen
pip isntall requests
4.修改fastdfs配置文件:client_config

# connect timeout in seconds
# default value is 30s
connect_timeout=30

# network timeout in seconds
# default value is 30s
network_timeout=60

# the base path to store log files

# 日志存放路径  
base_path=../../logs    

# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address
# tracker服务器
tracker_server=192.168.11.200:22122     

#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info

# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false

# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600

# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false

# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false

# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf


#HTTP settings
http.tracker_server_port=80

#use "#include" directive to include HTTP other settiongs
##include http.conf

5.在 python 虚拟环境下进入 shell 终端进行上传测试

导入模块:
from fdfs_client.client import Fdfs_client

导入配置文件
注意:windows环境下绝对路径会发生转义,需要加上 "r" 说明是原生字符串
client = Fdfs_client(r'配置文件绝对路径')

上传图片
注意:windows环境下绝对路径会发生转义,需要加上 "r" 说明是原生字符串
client.upload_by_filename(r'图片文件绝对路径')

上传测试成功!
上传测试

总结

1.修改lib/fdfs_client/storage_client.py文件,注释第12行;
2.windows环境下路径分隔符是 ‘\’ ,而linux使用 ‘/’,所以需要使用 ‘r’ 来声明是原生字符串;
3.如果上传文件提示连接tracker失败,请仔细检查client_config配置文件,配置文件中一定不要出现中文;
4.如果刚开始使用 pip install fdfs_client,报错,不要盲目安装VC++ 14.0,可以先去 控制面板==>>程序==>>程序和功能 查看是否已经安装过。

<think>好的,用户之前让我帮忙将一段C51的SPI函数移植到STM32,现在用户补充说他们使用的是模拟SPI,需要再改一下。我需要回顾之前的对话和解决方案,看看是否需要调整。 首先,用户之前的代码是C51的,存在三个问题:缺少MOSI操作、变量未定义、时钟时序错误。我之前给出的STM32解决方案已经考虑了硬件SPI的配置,比如GPIO初始化和时序调整,但用户现在明确使用模拟SPI,可能需要更详细的GPIO控制。 用户当前的请求是“改一下”,可能意味着他们需要更具体的模拟SPI实现,或者对之前的代码进行调整。模拟SPI通常指的是通过GPIO引脚手动控制时钟、数据线,而不使用硬件SPI外设。因此,需要确保代码完全通过GPIO操作来实现SPI协议。 回顾之前的回答,步骤1已经定义了GPIO引脚和电平操作宏,步骤2实现了发送函数,这可能已经是模拟SPI的实现,但用户可能希望更明确的说明,或者需要调整某些部分,比如时序延迟、数据顺序等。 可能的疑问点:用户是否已经正确配置了GPIO引脚?是否了解模拟SPI和硬件SPI的区别?是否需要调整时钟极性和相位?之前的代码中使用了HAL_Delay,但实际可能需要更精确的延时,或者用户使用的STM32型号不同,需要不同的配置。 接下来,我需要确认模拟SPI的关键点:手动控制SCLK、MOSI、CS引脚,按照SPI模式(如模式0)的时序发送数据。可能需要根据设备的要求调整时钟极性和数据采样边沿。同时,确保CS信号在传输前后有正确的使能和禁用。 此外,用户可能没有提到MISO引脚,如果只是发送数据,可能不需要接收部分,但如果有双向通信,可能需要补充。不过用户的问题集中在sendbyte,所以可能只需关注发送函数。 需要检查之前的代码是否有遗漏,比如是否在每次循环中正确设置了MOSI电平,并且时钟脉冲的生成是否符合模式0的要求。另外,延时时间是否需要根据实际SPI速度调整,HAL_Delay(1)可能不够精确,但作为示例可能可以接受,用户可能需要根据实际情况修改。 最后,总结修改点:明确模拟SPI的GPIO配置,确保时序正确,提供可调整的延时,可能添加注释说明如何根据不同的SPI模式调整代码。同时,提醒用户根据实际硬件连接修改引脚定义,并测试时序是否符合外设要求。</think>--- ### **模拟SPI移植要点解析** #### **一、硬件连接确认** 需要明确以下引脚定义(示例使用GPIOA,请根据实际电路修改): ```c // 模拟SPI引脚定义 #define SIM_SPI_SCLK_PIN GPIO_PIN_5 // 时钟线 #define SIM_SPI_MOSI_PIN GPIO_PIN_7 // 主设备输出 #define SIM_SPI_MISO_PIN GPIO_PIN_6 // 主设备输入(可选) #define SIM_SPI_CS_PIN GPIO_PIN_4 // 片选信号 // 端口定义 #define SIM_SPI_PORT GPIOA ``` #### **二、GPIO初始化配置** 在`MX_GPIO_Init()`函数中添加: ```c /* 模拟SPI引脚初始化 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; // SCLK & MOSI & CS 配置为推挽输出 GPIO_InitStruct.Pin = SIM_SPI_SCLK_PIN | SIM_SPI_MOSI_PIN | SIM_SPI_CS_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速模式 HAL_GPIO_Init(SIM_SPI_PORT, &GPIO_InitStruct); // MISO 配置为上拉输入(如果使用接收功能) GPIO_InitStruct.Pin = SIM_SPI_MISO_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 输入模式 GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉电阻 HAL_GPIO_Init(SIM_SPI_PORT, &GPIO_InitStruct); // 初始状态设置 SIM_SPI_SCLK_LOW(); // 时钟线初始低电平(模式0) SIM_SPI_MOSI_LOW(); // 数据线初始低电平 SIM_SPI_CS_HIGH(); // 片选初始不激活 ``` --- ### **三、核心发送函数实现** #### **模式0(CPOL=0, CPHA=0)时序实现** ```c // 电平操作宏(使用HAL库标准写法) #define SIM_SPI_SCLK_HIGH() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_SCLK_PIN, GPIO_PIN_SET) #define SIM_SPI_SCLK_LOW() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_SCLK_PIN, GPIO_PIN_RESET) #define SIM_SPI_MOSI_HIGH() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_MOSI_PIN, GPIO_PIN_SET) #define SIM_SPI_MOSI_LOW() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_MOSI_PIN, GPIO_PIN_RESET) #define SIM_SPI_CS_HIGH() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_CS_PIN, GPIO_PIN_SET) #define SIM_SPI_CS_LOW() HAL_GPIO_WritePin(SIM_SPI_PORT, SIM_SPI_CS_PIN, GPIO_PIN_RESET) void SIM_SPI_SendByte(uint8_t data) { SIM_SPI_CS_LOW(); // 启动传输 for(uint8_t i = 0; i < 8; i++) { // 设置MOSI电平(在时钟上升沿前稳定) (data & 0x80) ? SIM_SPI_MOSI_HIGH() : SIM_SPI_MOSI_LOW(); data <<= 1; // 左移发送MSB优先 // 生成时钟脉冲(模式0时序) SIM_SPI_SCLK_HIGH(); // 上升沿时从机采样 HAL_Delay(1); // 保持高电平时间(根据设备要求调整) SIM_SPI_SCLK_LOW(); // 下降沿恢复空闲 HAL_Delay(1); // 保持低电平时间 } SIM_SPI_CS_HIGH(); // 结束传输 } ``` --- ### **四、关键参数对照表** | 参数 | 模式0配置 | 模式3配置 | |-----------------|--------------------------|--------------------------| | CPOL (极性) | 0 (SCLK空闲低电平) | 1 (SCLK空闲高电平) | | CPHA (相位) | 0 (第一个边沿采样) | 1 (第二个边沿采样) | | 数据采样时刻 | SCLK上升沿 | SCLK下降沿 | | 数据切换时刻 | SCLK下降沿之后 | SCLK上升沿之后 | | 典型应用设备 | 多数SPI Flash | SD卡 | --- ### **五、时序优化技巧** #### **微秒级延时实现** ```c // 在stm32xxxx_hal.h中添加微秒延时函数 void delay_us(uint16_t us) { uint32_t ticks = us * (SystemCoreClock / 1000000); uint32_t start = DWT->CYCCNT; while((DWT->CYCCNT - start) < ticks); } // 在main.c中初始化DWT void DWT_Init(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } ``` #### **优化后的发送函数** ```c void SIM_SPI_FastSend(uint8_t data) { SIM_SPI_CS_LOW(); for(uint8_t i = 8; i > 0; i--) { // 数据提前设置 (data & 0x80) ? SIM_SPI_MOSI_HIGH() : SIM_SPI_MOSI_LOW(); data <<= 1; // 紧凑时序控制 SIM_SPI_SCLK_HIGH(); delay_us(2); // 高电平持续时间2μs SIM_SPI_SCLK_LOW(); delay_us(2); // 低电平持续时间2μs } SIM_SPI_CS_HIGH(); } ``` --- ### **六、调试技巧** #### **示波器测量点** 1. **建立时间测量** MOSI数据应在SCLK上升沿前稳定,满足: $$t_{su} > t_{SCLK\_high} - t_{MOSI\_setup}$$ 2. **保持时间验证** 数据在SCLK下降沿后仍需保持: $$t_{hold} > t_{SCLK\_low\_delay}$$ #### **逻辑分析仪解码** 使用PulseView设置SPI解码器时,注意配置: - **Clock Phase**:对应CPHA参数 - **Bit Order**:选择MSB First - **CS Active Low**:根据实际片选极性设置 --- ### **七、多设备扩展方案** ```c typedef enum { SPI_DEV_FLASH = 0, SPI_DEV_SDCARD, SPI_DEV_LCD } SPI_Device; void SIM_SPI_SendToDevice(SPI_Device dev, uint8_t data) { // 关闭所有片选 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET); // 选择目标设备 switch(dev) { case SPI_DEV_FLASH: HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); break; case SPI_DEV_SDCARD: HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); break; case SPI_DEV_LCD: HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); break; } SIM_SPI_SendByte(data); // 恢复片选状态 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET); } ``` --- ### **八、完整驱动文件示例** 创建`sim_spi.h`和`sim_spi.c`: **sim_spi.h** ```c #pragma once #include "stm32f1xx_hal.h" void SIM_SPI_Init(void); void SIM_SPI_SendByte(uint8_t data); uint8_t SIM_SPI_ReceiveByte(void); void SIM_SPI_SendToDevice(SPI_Device dev, uint8_t data); ``` **sim_spi.c** ```c #include "sim_spi.h" // 引脚配置(根据实际修改) #define SPI_PORT GPIOA #define SCLK_PIN GPIO_PIN_5 #define MOSI_PIN GPIO_PIN_7 #define MISO_PIN GPIO_PIN_6 #define CS_PIN GPIO_PIN_4 void SIM_SPI_Init(void) { // GPIO初始化代码(同第二部分) // ... } // 发送/接收函数实现(同第三、第五部分) // ... ``` --- **移植验证步骤**: 1. 用示波器测量SCLK频率是否符合目标设备要求 2. 发送0xAA(二进制10101010)验证波形规律性 3. 与目标设备进行简单数据交互测试 4. 逐步降低延时参数直到达到设备最大支持速度
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值