windows KMDF驱动中怎样设定SPI速率

问题:外围设备的KMDF驱动中,使用SPB框架实现的客户端驱动,怎样实现代码设定SPI的速率?
注意不是spbcx框架的控制器驱动程序
已经实现了通过远程目标target进行数据的收发
开发环境:windows 10开发平台,使用WDF框架开发的KMDF客户端驱动
使用了SPB框架
若能解决,有赏

在WindowsKMDF驱动中,可以使用WdfSpiTargetSetBusConfig函数来设定SPI速率。该函数接受一个WDF_SPI_CONFIG结构体作为参数,其中包含了SPI总线的配置信息,包括SPI速率。


//SPI 速度设置函数
//SpeedSet:
//SPI_SPEED_2   2分频   (SPI 12M    --sys 24M)
//SPI_SPEED_8   8分频   (SPI 3M     --sys 24M)
//SPI_SPEED_16  16分频  (SPI 1.5M    --sys 24M)
//SPI_SPEED_256 256分频 (SPI  905.6K --sys 24M)
void SPI1_SetSpeed(u8 SpeedSet)
{
         SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
     if(SpeedSet==SPI_SPEED_2)//二分频
     {
          SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz 
     }else if(SpeedSet==SPI_SPEED_8)//八分频 
     {
          SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz 
     }else if(SpeedSet==SPI_SPEED_16)//十六分频
     {
          SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
     }

    else      //256分频
     {
          SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
     }
     SPI1->CR1|=1<<6; //SPI设备使能   
} 

我的驱动程序是客户端的驱动程序,不是控制器驱动程序,无法获得SPB_CONTEXT

下面是一个设置SPI速率的示例代码:

SPB_TRANSFER_LIST_AND_ENTRIES(2) SpbTransferList = {0};
SPB_TRANSFER_LIST_ENTRY SpbTransferListEntries[2] = {0};

// 设置SPI时钟极性和相位
SpbTransferListEntries[0].Flags = SPB_TRANSFER_LIST_FLAG_WRITE;
SpbTransferListEntries[0].DelayInUs = 0;
SpbTransferListEntries[0].BufferSize = 1;
SpbTransferListEntries[0].Buffer[0] = SPI_MODE_0;

// 设置SPI传输速率
SpbTransferListEntries[1].Flags = SPB_TRANSFER_LIST_FLAG_WRITE;
SpbTransferListEntries[1].DelayInUs = 0;
SpbTransferListEntries[1].BufferSize = 2;
SpbTransferListEntries[1].Buffer[0] = (CCHAR)(SPI_CLOCK_DIVIDER >> 8);
SpbTransferListEntries[1].Buffer[1] = (CCHAR)(SPI_CLOCK_DIVIDER & 0xFF);

// 将设置封装到SPB_TRANSFER_LIST中
SpbTransferList.TotalTransfers = 2;
SpbTransferList.Transfers = SpbTransferListEntries;

// 调用SPB库函数发送SPB_REQUEST_PACKET
status = SpbWriteDataSynchronously(SpbDevice, &SpbTransferList, NULL);

其中,SPI_MODE_0为时钟极性为0,相位为0的SPI模式。SPI_CLOCK_DIVIDER为设置的SPI速率,可以通过修改这个参数来改变传输速率。

可以参考下这个实例中的思路:kmdf驱动教程2——驱动程序与应用程序通信,链接:https://blog.csdn.net/hustd10/article/details/50589743

https://www.baidu.com/link?url=r7Kx_ADmi2wM9qeeFfKnMd3IFCgsdBxuUqpUeyOzLaaXFWq4Upgwl4U_p4gMwNLcanwF3Z6Hn7l58_4QrR651nwBqXT8gT44tO4AC5ODiaa&wd=&eqid=bf6c02f60011b5de0000000263ef565c

在Windows KMDF驱动中设置SPI总线的速率需要使用SPB框架。SPB框架提供了一个通用的SPI接口,用于与各种外设通信。为了设定SPI的速率,需要在驱动中实现EvtDevicePrepareHardware回调函数,并使用SPB框架的SpbPeripheralGetConnectionParameters函数获取连接参数。在这个函数中,可以指定SPI总线的速率。例如:

NTSTATUS
EvtDevicePrepareHardware(
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
    )
{
    NTSTATUS status;
    SPB_CONNECTION_PARAMETERS spiConnectionParams;

    // Get the SPB target from the device context
    SPB_TARGET *spiTarget = GetSpbTarget(Device);

    // Get the SPI connection parameters
    RtlZeroMemory(&spiConnectionParams, sizeof(SPB_CONNECTION_PARAMETERS));
    status = SpbPeripheralGetConnectionParameters(
        spiTarget,
        &spiConnectionParams,
        sizeof(SPB_CONNECTION_PARAMETERS)
        );

    if (!NT_SUCCESS(status)) {
        // Failed to get connection parameters
        return status;
    }

    // Set the SPI clock frequency to 1MHz
    spiConnectionParams.ConnectionParameters.SpiConnectionParameters.SpiClockFrequency = 1000000;

    // Set the SPI connection parameters
    status = SpbPeripheralSetConnectionParameters(
        spiTarget,
        &spiConnectionParams,
        sizeof(SPB_CONNECTION_PARAMETERS)
        );

    if (!NT_SUCCESS(status)) {
        // Failed to set connection parameters
        return status;
    }

    return status;
}

在 Windows KMDF 驱动中设定 SPI 速率,需要使用 SPI 的 IOCTL 来设置,其中包括两个关键参数:

SPI transfer parameters structure:该结构体包含了 SPI 数据传输的一些参数,例如传输类型、带宽等。

IOCTL SPI_GET_DEVICE_PROPERTY:该 IOCTL 获取 SPI 设备的属性,例如最大时钟频率等。

以下是一个基本的 KMDF SPI 驱动程序中设定 SPI 时钟速率的代码示例:

SPI_TRANSFER_PARAMETERS spiParams;
ULONG maxFrequency;

// 获取 SPI 设备的最大时钟频率
IoctlStatus = WdfIoTargetSendIoctlSynchronously(
                  IoTarget,
                  NULL,
                  IOCTL_SPI_GET_DEVICE_PROPERTY,
                  NULL,
                  0,
                  &maxFrequency,
                  sizeof(maxFrequency),
                  NULL);

if (!NT_SUCCESS(IoctlStatus)) {
    // 处理 IOCTL 错误
}

// 设置 SPI 数据传输参数
RtlZeroMemory(&spiParams, sizeof(spiParams));
spiParams.Size = sizeof(spiParams);
spiParams.SpiMode = SPI_MODE_0;
spiParams.MaxFrequency = maxFrequency; // 使用 SPI 设备的最大时钟频率

// 执行 SPI 数据传输
IoctlStatus = WdfIoTargetSendIoctlSynchronously(
                  IoTarget,
                  NULL,
                  IOCTL_SPI_TRANSFER,
                  &spiParams,
                  sizeof(spiParams),
                  NULL,
                  0,
                  NULL);

if (!NT_SUCCESS(IoctlStatus)) {
    // 处理 IOCTL 错误
}

需要注意的是,以上代码仅为示例,实际情况中需要根据具体的 SPI 设备和应用需求进行相应的调整。另外,SPI 设备的具体使用方法也需要参考相关文档或者参考硬件厂商提供的驱动程序

在 KMDF 驱动中,可以通过 SPB(Serial Peripheral Bus)框架来控制 SPI 总线的速率。

具体实现过程如下:

在驱动的 EvtDeviceAdd 回调函数中,调用 WdfDeviceCreateDeviceInterface 函数来创建驱动程序的设备接口。

在驱动程序中,使用 WdfDeviceOpenRegistryKey 函数打开驱动程序注册表键,然后使用 WdfRegistryQueryValue 函数获取 SPI 总线的相关信息,例如 SPI 总线的频率。

在驱动程序中,使用 WdfDeviceRetrieveDeviceProperty 函数获取指向 SPB 控制器设备对象的指针,并调用 SpbControllerGetConnectionSettings 函数获取连接设置,包括 SPI 总线的时钟源和时钟频率。

使用 SpbControllerSetTargetConnectionSettings 函数将 SPI 总线的时钟频率设置为需要的频率。

完成 SPI 总线的初始化后,可以使用 SPB 框架提供的其他函数进行 SPI 数据

在KMDF驱动程序中,可以使用SPB框架提供的函数来设定SPI总线的速率。具体来说,可以使用SPB_CONTROLLER_CONFIG_INIT宏和SPB_CONTROLLER_CONFIG结构体来设定SPI总线的参数,其中包括时钟频率(即速率)等。

以下是一个示例代码,用于设定SPI总线的速率:

NTSTATUS status;
SPB_CONTROLLER_CONFIG spbConfig;
SPB_CONNECTION_PARAMETERS spbConnectionParams;

// 初始化SPB控制器配置
SPB_CONTROLLER_CONFIG_INIT(&spbConfig, 0);
spbConfig.ConnectionParametersPtr = &spbConnectionParams;

// 设定SPI总线速率
spbConfig.SpbDriverParameters.SpiConnectionParameters.SpiClockFrequency = 1000000; // 1MHz

// 通过SPB框架创建SPB连接对象
status = SpbDeviceCreateConnection(Device, &spbConfig, &Connection);
if (!NT_SUCCESS(status))
{
    // 连接创建失败,处理错误
}

在以上代码中,我们先使用SPB_CONTROLLER_CONFIG_INIT宏来初始化SPB_CONTROLLER_CONFIG结构体,并将ConnectionParametersPtr字段设定为&spbConnectionParams,这是一个SPB_CONNECTION_PARAMETERS结构体对象。

接着,我们通过spbConfig.SpbDriverParameters.SpiConnectionParameters.SpiClockFrequency字段,将SPI总线的速率设定为1MHz,即1000000。最后,通过SpbDeviceCreateConnection函数创建SPB连接对象,并将spbConfig作为参数传递进去。

注意,在实际开发中,需要根据自己的具体情况调整速率等参数。另外,如果需要更复杂的SPI控制,也可以参考SPB框架提供的其他函数和结构体。

该回答引用ChatGPT
您可以使用SPB框架中的SpbRequestBusSpeed函数来设置SPI的速率,该函数接受一个参数,即要设置的SPI速率,可以使用SPB_BUS_SPEED_XXX宏来设置不同的速率,其中XXX表示要设置的速率,例如SPB_BUS_SPEED_FULL表示设置为最大速率。