USB自定义HID设备实现-STM32

发布者:等放假的Lwj最新更新时间:2017-01-13 来源: eefocus关键字:USB  HID设备  STM32 手机看文章 扫描二维码
随时随地手机看文章

该文档使用USB固件库,在其基础上进行了自己的定制,完成了一个USB-HID设备,首先是usb_desc.c文件,里面存放了usb各种描述符的存在

#include "usb_desc.h"

 

//usb标准设备描述符

const u8 DinkUsbDeviceDescriptor[DINK_USB_SIZ_DEVICE_DESC] = {

 

    USB_DEVICE_DESC_SIZE,             //bLength字段。设备描述符的长度为18(0x12)字节

    USB_DEVICE_DESCRIPTOR_TYPE,           //bDescriptorType字段。设备描述符的编号为0x01

    WBVAL(0x0200),                       //bcdUSB字段。这里设置版本为USB1.1,即0x0110。

    0x00,                             //bDeviceClass字段。我们不在设备描述符中定义设备类,

    0x00,                              //bDeviceSubClass字段。bDeviceClass字段为0时,该字段也为0。

    0x00,                              //bDeviceProtocol字段。bDeviceClass字段为0时,该字段也为0。

    0x40,                               //bMaxPacketSize0字段。端点0的最大包长度。

    WBVAL(0x7777),                       //idVender字段。厂商ID号,我们这里取0x8888,仅供实验用。

    WBVAL(0x8888),                       //idProduct字段。产品ID号,由于是第一个实验,我们这里取0x0001。\。

    WBVAL(0x0100),                     // 设备的版本

    0x01,                             //iManufacturer字段。厂商字符串的索引值,为了方便记忆和管理

    0x02,                             //iProduct字段。产品字符串的索引值。刚刚用了1,这里就取2吧。

    0x03,                              //iSerialNumber字段。设备的序列号字符串索引值。

    0x01                                //bNumConfigurations字段。该设备所具有的配置数。

};

 

 

//USB报告描述符的定义

const u8 HID_ReportDescriptor[]=

{

0x06,0xA0,0xFF,//用法页(FFA0h, vendor defined)

0x09, 0x01,//用法(vendor defined)

0xA1, 0x01,//集合(Application)

0x09, 0x02 ,//用法(vendor defined)

0xA1, 0x00,//集合(Physical)

0x06,0xA1,0xFF,//用法页(vendor defined)

//输入报告

0x09, 0x03 ,//用法(vendor defined)

0x09, 0x04,//用法(vendor defined)

0x15, 0x80,//逻辑最小值(0x80 or -128)

0x25, 0x7F,//逻辑最大值(0x7F or 127)

0x35, 0x00,//物理最小值(0)

0x45,0xFF,//物理最大值(255)

0x75, 0x08,//报告长度Report size (8位)

0x95, 0x40,//报告数值(64 fields)

0x81, 0x02,//输入(data, variable, absolute)

//输出报告

0x09, 0x05,//用法(vendor defined)

0x09, 0x06,//用法(vendor defined)

0x15, 0x80,//逻辑最小值(0x80 or -128)

0x25, 0x7F,//逻辑最大值(0x7F or 127)

0x35, 0x00,//物理最小值(0)

0x45,0xFF,//物理最大值(255)

0x75,0x08,//报告长度(8位)

0x95, 0x40,//报告数值(64 fields)

0x91, 0x02,//输出(data, variable, absolute)

0xC0,//集合结束(Physical)

0xC0//集合结束(Application)

};

//通过上面的报告描述符的定义,我们知道返回的输入报告具有8字节。

//输出报告也有64字节。至于这64字节的数据是干什么用的,就要由用户

//自己来决定了。

///////////////////////////报告描述符完毕////////////////////////////

 

 

//usb配置描述符

const u8 DinkUsbConfigDescriptor[DINK_USB_SIZ_CONFIG_DESC] = {

    /***************配置描述符***********************/

    USB_CONFIGUARTION_DESC_SIZE,       //bLength字段。配置描述符的长度为9字节。

    USB_CONFIGURATION_DESCRIPTOR_TYPE, //bDescriptorType字段。配置描述符编号为0x02。

    //wTotalLength字段。配置描述符集合的总长度,

    //包括配置描述符本身、接口描述符、类描述符、端点描述符等。

    WBVAL( 

    USB_CONFIGUARTION_DESC_SIZE +           //配置描述符

    USB_INTERFACE_DESC_SIZE     +        //接口1描述符

    9                           +           //hid描述符

    USB_ENDPOINT_DESC_SIZE      +           //端点描述符

    USB_ENDPOINT_DESC_SIZE                  //端点描述符

    ),

    0x01,                                   //bNumInterfaces字段。该配置包含的接口数,只有一个接口。

    0x01,                                   //bConfiguration字段。该配置的值为1。

    0x00,                                  //iConfigurationz字段,该配置的字符串索引。这里没有,为0。

    USB_CONFIG_BUS_POWERED ,                //bmAttributes字段,该设备的属性

    USB_CONFIG_POWER_MA(500),                  //bMaxPower字段,该设备需要的最大电流量

 

    /*********************第一个接口描述符,hid设备**********************/

    USB_INTERFACE_DESC_SIZE,              //bLength字段。接口描述符的长度为9字节。

    USB_INTERFACE_DESCRIPTOR_TYPE,           //bDescriptorType字段。接口描述符的编号为0x04。

    0x00,                                  //bInterfaceNumber字段。该接口的编号,第一个接口,编号为0。

    0x00,                                  //bAlternateSetting字段。该接口的备用编号,为0。

    0x02,                                   //bNumEndpoints字段。非0端点的数目。该接口有2个批量端点

 

    USB_DEVICE_CLASS_HUMAN_INTERFACE,       //bInterfaceClass字段。该接口所使用的类。大容量存储设备接口类的代码为0x08。,

   

    0x00,                                   //bInterfaceSubClass字段。该接口所使用的子类。在HID1.1协议中,

                                            //只规定了一种子类:支持BIOS引导启动的子类。

                                            //USB键盘、鼠标属于该子类,子类代码为0x01。

                                            //但这里我们是自定义的HID设备,所以不使用子类。

   

    0x00,                                   //bInterfaceProtocol字段。如果子类为支持引导启动的子类,

                                            //则协议可选择鼠标和键盘。键盘代码为0x01,鼠标代码为0x02。

                                            //自定义的HID设备,也不使用协议。

 

    0x00,                                   //iConfiguration字段。该接口的字符串索引值。这里没有,为0。

 

    /*********************HID报告描述符*************************/

    //bLength字段。本HID描述符下只有一个下级描述符。所以长度为9字节。

     0x09,

     

     //bDescriptorType字段。HID描述符的编号为0x21。

     0x21,

     

     //bcdHID字段。本协议使用的HID1.1协议。注意低字节在先。

     0x10,

     0x01,

     

     //bCountyCode字段。设备适用的国家代码,这里选择为美国,代码0x21。

     0x21,

     

     //bNumDescriptors字段。下级描述符的数目。我们只有一个报告描述符。

     0x01,

     

     //bDescriptorType字段。下级描述符的类型,为报告描述符,编号为0x22。

     0x22,

     

     //bDescriptorLength字段。下级描述符的长度。下级描述符为报告描述符。

     sizeof(HID_ReportDescriptor)&0xFF,

     (sizeof(HID_ReportDescriptor)>>8)&0xFF,

    /*********************端点描述符**********************************/

    /* 端点描述符 */

    USB_ENDPOINT_DESC_SIZE,                //bLength字段。端点描述符长度为7字节。

    USB_ENDPOINT_DESCRIPTOR_TYPE,            //bDescriptorType字段。端点描述符编号为0x05。

    USB_ENDPOINT_IN(1),                     //bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。

    USB_ENDPOINT_TYPE_INTERRUPT,              //bmAttributes字段。D1~D0为端点传输类型选择。

    WBVAL(0x0040),                           //wMaxPacketSize字段。该端点的最大包长。最大包长为64字节。

    0x01,                                        //bInterval字段。端点查询的时间,端点查询的时间,此处无意义。

    /***********************端点描述符*******************************************/

    USB_ENDPOINT_DESC_SIZE,                //bLength字段。端点描述符长度为7字节。

    USB_ENDPOINT_DESCRIPTOR_TYPE,            //bDescriptorType字段。端点描述符编号为0x05。

    USB_ENDPOINT_OUT(1),                    //bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。

    USB_ENDPOINT_TYPE_INTERRUPT,              //bmAttributes字段。D1~D0为端点传输类型选择。

    WBVAL(0x0040),                           //wMaxPacketSize字段。该端点的最大包长。最大包长为64字节。

    0x01,                                        //bInterval字段。端点查询的时间,端点查询的时间,此处无意义。

};

 

 

 

 

 

/************************语言ID的定义********************/

const u8 DinkUsbLanguageId[DINK_USB_SIZ_STRING_LANGID]=

{

    0x04, //本描述符的长度

    0x03, //字符串描述符

    //0x0409为美式英语的ID

    0x09,

    0x04

};

 

 

////////////////////////语言ID完毕//////////////////////////////////

 

//Unicode 字符串描述符

//邓小俊的usb鼠标

const u8 DinkUsbManufacturerStringDescriptor[DINK_USB_SIZ_STRING_VENDOR]=

{

    32,         //该描述符的长度为32字节

    0x03,       //字符串描述符的类型编码为0x03

    0x44, 0x00, //D

    0x49, 0x00, //I

    0x4e, 0x00, //N

    0x4b, 0x00, //K

    0x5f, 0x00, //_

    0x48, 0x00, //H

    0x49, 0x00, //I

    0x44, 0x00, //D

    0x5f, 0x00, //_

    0x44, 0x00, //D

    0x45, 0x00, //E

    0x56, 0x00, //V

    0x49, 0x00, //I

    0x43, 0x00, //C

    0x45, 0x00  //E

 

};

/////////////////////////厂商字符串结束/////////////////////////////

 

 

//产品字符串描述符

const u8 DinkUsbProductStringDescriptor[DINK_USB_SIZ_STRING_PRODUCT]=

{

    32,         //该描述符的长度为32字节

    0x03,       //字符串描述符的类型编码为0x03

    0x44, 0x00, //D

    0x49, 0x00, //I

    0x4e, 0x00, //N

    0x4b, 0x00, //K

    0x5f, 0x00, //_

    0x48, 0x00, //H

    0x49, 0x00, //I

    0x44, 0x00, //D

    0x5f, 0x00, //_

    0x44, 0x00, //D

    0x45, 0x00, //E

    0x56, 0x00, //V

    0x49, 0x00, //I

    0x43, 0x00, //C

    0x45, 0x00  //E

};

////////////////////////产品字符串结束////////////////////////////

 

//字符串“2008-07-07”的Unicode编码

//8位小端格式

const u8 DinkUsbSerialNumberStringDescriptor[DINK_USB_SIZ_STRING_SERIAL]={

    22,         //该描述符的长度为22字节

    0x03,       //字符串描述符的类型编码为0x03

    0x32, 0x00, //2

    0x30, 0x00, //0

    0x31, 0x00, //1

    0x35, 0x00, //5

    0x2d, 0x00, //-

    0x30, 0x00, //0

    0x33, 0x00, //3

    0x2d, 0x00, //-

    0x32, 0x00, //2

    0x31, 0x00  //1

};

//////////////////////产品序列号字符串结束/////////////////////////

 

//产品序列号

u8 DinkUsbStringSerialUniqueId[DINK_USB_SIZ_STRING_SERIAL_UNIQUE_ID] =

{

    DINK_USB_SIZ_STRING_SERIAL_UNIQUE_ID,        //描述符长度

    0x03                                                      //描述符类型编码

/* Serial number该编码将会

 

可以通过修改该文件实现不同的设备,第二是usb_prop.c文件,定义了一系列的回调函数,在usb枚举阶段使用

#include "usb_prop.h"

 

u32 ProtocolValue;

 

//表明有多少端点,多少种配置

DEVICE Device_Table =

{

    EP_NUM,

    1

};

 

//static u8 s_Request = 0;//记录当前请求值

 

//设备描述符

ONE_DESCRIPTOR Device_Descriptor =

{

    (u8*)DinkUsbDeviceDescriptor,

    DINK_USB_SIZ_DEVICE_DESC

};

 

//配置描述符

ONE_DESCRIPTOR Config_Descriptor =

{

    (u8*)DinkUsbConfigDescriptor,

    DINK_USB_SIZ_CONFIG_DESC

};

//报告描述符

ONE_DESCRIPTOR DinkUsb_Report_Descriptor =

{

    (u8*)HID_ReportDescriptor,

    HID_ReportDescSize

};

 

//报告描述符

ONE_DESCRIPTOR DinkUsb_Hid_Descriptor =

{

    (u8*)(DinkUsbConfigDescriptor+9),

    9

};

 

 

 

//字符串描述符

ONE_DESCRIPTOR String_Descriptor[4] =

{

    {(u8*)DinkUsbLanguageId, DINK_USB_SIZ_STRING_LANGID},

    {(u8*)DinkUsbManufacturerStringDescriptor, DINK_USB_SIZ_STRING_VENDOR},

    {(u8*)DinkUsbProductStringDescriptor, DINK_USB_SIZ_STRING_PRODUCT},

    {(u8*)DinkUsbSerialNumberStringDescriptor, DINK_USB_SIZ_STRING_SERIAL}

};

 

 

 

//USB过程处理函数数组

DEVICE_PROP Device_Property =

{

    DinkUsbInit,

    DinkUsbReset,

    DinkUsbStatus_In,

    DinkUsbStatus_Out,

    DinkUsbData_Setup,

    DinkUsbNoDataSetup,

    DinkUsbGetInterfaceSetting,

    DinkUsbGetDeviceDescriptor,

    DinkUsbGetConfigDescriptor,

    DinkUsbGetStringDescriptor,

    0,

    0x40 /*MAX PACKET SIZE*/

};

 

//usb标准数据请求结构体

//只实现了两个,剩下的用nop方式解决了

USER_STANDARD_REQUESTS User_Standard_Requests =

{

    DinkUsbGetConfiguration,

    DinkUsbSetConfiguration,

    DinkUsbGetInterface,

    DinkUsbSetInterface,

    DinkUsbGetStatus,

    DinkUsbClearFeature,

    DinkUsbSetEndPointFeature,

    DinkUsbSetDeviceFeature,

    DinkUsbSetDeviceAddress

};

 

 

 

//设备初始化

void DinkUsbInit(void)

{

    Get_SerialNum();        //构建字符串描述符

    pInformation->Current_Configuration = 0;      //当前选择的配置为0

    PowerOn();          //连接USB

    _SetISTR(0);

    wInterrupt_Mask = IMR_MSK;

    _SetCNTR(wInterrupt_Mask);

    bDeviceState = UNCONNECTED;   //设备状态初始化为未连接状态

    usb_debug_printf("USB Init\r\n");

}

 

//设备复位

void DinkUsbReset(void)

{

    Device_Info.Current_Configuration = 0;  //选择当前配置为0

    pInformation->Current_Feature = DinkUsbConfigDescriptor[7]; //获取配置描述符中当前设备属性

    pInformation->Current_Interface = 0;//设置当前设备接口

    SetBTABLE(BTABLE_ADDRESS);//设置缓冲区地址

   

    SetEPType(ENDP0, EP_CONTROL);//控制端点

    SetEPTxStatus(ENDP0, EP_TX_STALL);

    SetEPRxAddr(ENDP0, ENDP0_RXADDR);//设置端点缓冲区地址

    SetEPTxAddr(ENDP0, ENDP0_TXADDR);

    Clear_Status_Out(ENDP0);

    SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);//设置接收最大长度

    SetEPRxValid(ENDP0);

   

    SetEPType(ENDP1, EP_INTERRUPT);//初始化端点1为中断传输模式,用来报告一些状态

    SetEPTxAddr(ENDP1, ENDP1_TXADDR);//设置端点地址

    SetEPRxAddr(ENDP1, ENDP1_RXADDR);//设置端点地址

    SetEPRxStatus(ENDP1, EP_RX_VALID);//使能接收

    SetEPTxStatus(ENDP1, EP_TX_NAK);  //不使能发送

    SetEPRxCount(ENDP1, 64);//设置接收最大长度

    Clear_Status_Out(ENDP1);

 

    bDeviceState = ATTACHED;//设备插入

   

    SetDeviceAddress(0);//设置当前地址为0

    usb_debug_printf("USB Reset\r\n");

}

 

//不知道干嘛的

void DinkUsbStatus_In(void)

{

    return;

}

//不知道干嘛的

void DinkUsbStatus_Out(void)

{

    return;

}

 

u8 *DinkUsbGetReportDescriptor(u16 Length)

{

    usb_debug_printf("获取报告描述符\r\n");

    return Standard_GetDescriptorData(Length, &DinkUsb_Report_Descriptor);

}

 

u8 *DinkUsbGetHIDDescriptor(u16 Length)

{

    usb_debug_printf("获取HID述符\r\n");

    return Standard_GetDescriptorData(Length, &DinkUsb_Hid_Descriptor);

}

 

u8 *DinkUsbGetProtocolValue(u16 Length)

{

    usb_debug_printf("获取协议\r\n");

    if (Length == 0)

    {

        pInformation->Ctrl_Info.Usb_wLength = 1;

        return NULL;

    }

    else

    {

        return (u8 *)(&ProtocolValue);

    }

}

 

RESULT DinkUsbData_Setup(u8 RequestNo)

{

    u8 *(*CopyRoutine)(u16);

 

    CopyRoutine = NULL;

    if ((RequestNo == GET_DESCRIPTOR)

    && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))

    && (pInformation->USBwIndex0 == 0))

    {

        //获取报告描述符

        if (pInformation->USBwValue1 == REPORT_DESCRIPTOR)

        {

            CopyRoutine = DinkUsbGetReportDescriptor;

        }

        //获取HID描述符

        else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE)

        {

            CopyRoutine = DinkUsbGetHIDDescriptor;

        }

 

    }

 

    /*** GET_PROTOCOL ***/

    else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))

       && RequestNo == GET_PROTOCOL)

    {

        CopyRoutine = DinkUsbGetProtocolValue;//获取协议值

    }

 

 

    if (CopyRoutine == NULL)

    {

        return USB_UNSUPPORT;

    }

 

    pInformation->Ctrl_Info.CopyData = CopyRoutine;

    pInformation->Ctrl_Info.Usb_wOffset = 0;

    (*CopyRoutine)(0);

    return USB_SUCCESS;

}

 

RESULT DinkUsbSetProtocol(void)

{

  u8 wValue0 = pInformation->USBwValue0;

  ProtocolValue = wValue0;

  return USB_SUCCESS;

}

 

RESULT DinkUsbNoDataSetup(u8 RequestNo)

{

    if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))

    && (RequestNo == SET_PROTOCOL))

    {

        usb_debug_printf("设置协议\r\n");

        return DinkUsbSetProtocol();

    }

    else

    {

        return USB_UNSUPPORT;

    }

}

 

 

RESULT DinkUsbGetInterfaceSetting(u8 Interface, u8 AlternateSetting)

{

    if (AlternateSetting > 0)//配置数量

    {

        usb_debug_printf("设置配置\r\n");

        return USB_UNSUPPORT;

    }

    else if (Interface > 1)//接口数量

    {

        usb_debug_printf("设置接口\r\n");

        return USB_UNSUPPORT;

    }

    return USB_SUCCESS;

}

 

//获取设备描述符

u8 *DinkUsbGetDeviceDescriptor(u16 Length)

{

    usb_debug_printf("获取设备描述符\r\n");

    return Standard_GetDescriptorData(Length, &Device_Descriptor);

}

//配置描述符

u8 *DinkUsbGetConfigDescriptor(u16 Length)

{

    usb_debug_printf("获取配置描述符\r\n");

    return Standard_GetDescriptorData(Length, &Config_Descriptor);

}

//字符串描述符

u8 *DinkUsbGetStringDescriptor(u16 Length)

{

 

    u8 wValue0 = pInformation->USBwValue0;

    usb_debug_printf("获取字符串描述符 %d\r\n",wValue0);

    if (wValue0 > 4)

    {

        return NULL;

    }

    else

    {

        return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]); //返回字符串描述符

    }

}

 

 

 

 

 

//将设备状态上传到配置数据中

void DinkUsbSetConfiguration(void)

{

 

    DEVICE_INFO *pInfo = &Device_Info;

    usb_debug_printf("设置配置\r\n");

    if (pInfo->Current_Configuration != 0)

    {

        bDeviceState = CONFIGURED;

    }

}

//将地址设置上传

void DinkUsbSetDeviceAddress (void)

{

    usb_debug_printf("设置地址\r\n");

    bDeviceState = ADDRESSED;

}

 

 

其中最核心的两个函数分别是复位和初始化,复位的时候要将端点配置好,并且接受最好要使能,否则无法接收数据(后期自己使能也可以),然后就是端点的处理函数了usb_endp.c

#include "usb_endp.h"

 

//发送完成置1 发送未完成置0

u8 sendOk = 1;

//接收到数据该设置为1,数据处理完成之后修改为0

u8 ReceiveOk = 0;

 

void EP1_IN_Callback(void)

{

    //设备向主机发送数据的回调函数

    sendOk = 1;//发送成功为1

    SetEPTxStatus(ENDP1, EP_TX_NAK);//发送成功等待第二次设置为valid

}

 

void EP1_OUT_Callback(void)

{

    //接收了一次数据之后等待数据处理,将接受响应设置为NAK

    //处理完成之后再设置为VALID

    SetEPRxStatus(ENDP1, EP_RX_NAK);//NAK接收

    ReceiveOk = 1;//有数据标志为1

 

}

 

要想使能这些函数,需要将端点响应函数打开

另外,单片机应当来处理或者发送数据,依靠usb_data_process.h文件完成

#include "usb_data_process.h"

 

 

//HID发送数据

//返回1发送失败 返回0发送成功

u8 HID_Send_Data(u8* buffer,u8 length)

{

    if(sendOk == 1)

    {

        if(length == 0)

        {

            SetEPTxStatus(ENDP1, EP_TX_NAK);//不发送

        }

        else

        {

            UserToPMABufferCopy(buffer, GetEPTxAddr(ENDP1), length);

            SetEPTxCount(ENDP1, length);

            SetEPTxValid(ENDP1);//使能发送

            sendOk = 0;//设置发送未完成状态,等待发送回调函数将数据发送到主机

        }

        return 0;

    }

    else

    {

        return 1;//上一次的数据还没发送出去,所以这次发送失败

    }

}

 

 

//HID接收数据处理

u8 HID_Receive_Data(u8* buffer)

{

    u16 length = 0;//获取接收到的数据长度

    u8 i = 0;

    if(ReceiveOk == 1)//有数据

    {

        length = GetEPRxCount(ENDP1);

        if(length == 0)return 0;

        else

        {

            PMAToUserBufferCopy(buffer, GetEPRxAddr(ENDP1), length);

            SetEPRxValid(ENDP1);//使能接收

            ReceiveOk = 0;

           

            printf("hid receive : ");

            for(i = 0; i < length; i++)

            {

                printf("%c ",buffer[i]);

            }

            printf("\r\n");

           

            return length;//返回接收到的数据

        }

    }

    else

    {

        //没有数据,直接为0

        return 0;

    }

}

 


关键字:USB  HID设备  STM32 引用地址:USB自定义HID设备实现-STM32

上一篇:HCSR04超声波传感器驱动
下一篇:STM32的通用定时器TIMx系统了解

推荐阅读最新更新时间:2024-03-16 15:30

USB接口单片机SL11R的特点及应用
    摘要: 介绍了USB接口单片机SL11R的主要特点,并简要地说明了SL11R基本应用系统的组成和开发。     关键词: USB 单片机 SL11R SL11R是Scanlogic公司生产的带有USB接口的16位RISC单片机,内核处理速度达48MIPS,有很强的控制功能和灵活的工作方式。SL11R固化有类似于80X86的内部BIOS,可以直接调用,使用非常简单,可以让开发者在很短的时间内完成设计任务。 1 USB接口简介 USB总线是通用串行总线(Universal Serial Bus)的简称,已经成为PC机的标准接口。目前256以上的PC机基本上都已经配置了USB接口。USB接口具
[应用]
STM32学习之路:I2C的基本读写
宏定义: /*I2C传输速度,最高为400kHz*/ #define I2C_SPEED 400000 /* STM32 自身的 I2C 地址, 这个地址只要与 STM32 外挂的 I2C 器件地址不一样即可 */ #define I2C_OWN_ADDR 0x77 /*EEPROM地址*/ #define EEPROM_ADDR (0x50 1) //0xA0 #define EEPROM_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define EEPROM_SCL_PIN GPIO_Pin_6 #define EEPROM_SCL_GPIO_PORT GPIOB #de
[单片机]
关于STM32中的GPIO位设置的相关纪要与总结
1.在对GPIOx_ODR的个别位进行编程时,软件不需要禁止中断。 2.GPIO具有锁定机制。主要是在一些关键引脚上为了防止程序跑掉而引起不必要的后果。 3.GPIO的库函数问题, GPIO_SetBits:置所选端口的一个或者多个位高; GPIO_ResetBits:相应的设置相应的一个或者多个位高; GPIO_Init:设置A,B,C,D,E端口的任一个I/O的输入输出配置信息,初始化I/O芯片; GPIO_Pin:设置带选择的引脚号(GPIO_Pin_1:选中1引脚); GPIO_Speed:设置所选中的引脚的频率(GPIO_Speed_10MHz); GPIO_Mode:设置所选中的引脚的工作状态,做以上几步都必须先定
[单片机]
STM32总线结构和存储器
也就说我们所操作的就是别名区的位
[单片机]
<font color='red'>STM32</font>总线结构和存储器
关于STM32软硬件兼容性相关的知识
Ⅰ、写在前面 很多朋友初学STM32的时候,对STM32芯片很多相关知识都不是很了解,导致了在学习的路上很迷茫,甚至半途放弃。希望本文的内容对初学的朋友有一定帮助。 常见问题: 1.我开发板是STM32F103ZE芯片,但网上找到的软件工程基于STM32F103R8芯片的,我能直接将工程下载并调试吗? 2.我有 STM32F205 R8的原理图和封装库,但现在需要画STM32F405RC芯片的板子,能直接替换使用吗? 以上问题在你阅读本文之后就会得到比较明确的答案。 关于本文的更多详情请往下看。 Ⅱ、本文要点 从本文的标题可以看得出来,主要是站在“STM32兼容性”的角度来分析问题。 在开发STM32项目中,
[单片机]
关于<font color='red'>STM32</font>软硬件兼容性相关的知识
详解STM32之SD卡
一、SD卡概述   1、定义   2、容量等级   3、SD卡框图   4、SD卡与TF卡的区别 二、 SD卡内部结构   1、 SD卡内部结构简图   2、 存储阵列结构图   3、Buffer   4、“存储阵列Block”--最小的存储单元   5、SD卡的特殊功能寄存器 三、SDIO接口 四、SD卡协议的核心--数据读、写、擦除   1、SD卡写数据块   2、SD卡读数据块   3、擦除SD卡 五、SD卡物理层协议   1、接口   2、命令格式   3、响应格式   4、SD卡的工作状态   5、SD卡的两种状态信息 六、STM32与SD卡相配的外设--SDIO适配器   1、SDIO adapter 结构图
[单片机]
详解<font color='red'>STM32</font>之SD卡
USB学习系列之四——USB包结构
1.USB的数据传输以包为单位,一个包被分成不同的域。USB传输时使用的是LSB在前,MSB在后的方式。 2.不同的包所包含的域是不同的,但是都有共同的特点是:以同步域开始,紧跟着一个包标识符PID,最终以包结束符EOP结束这个包。 3.同步域:高速USB串行接口引擎数据传输要开始了,同时也提供同步时钟。对于低速设备和全速设备,同步域使用的是0000 0001(二进制数);对于高速设备使用的是00000000 00000000 00000000 00000001。 注意:这个是对发送端的要求,接收端解码时,0的个数可以少于这个数目。 4.包结束符:包结束符一共有8位,其中USB协议使用的只有4位(PID0~PID3),另
[嵌入式]
142条STM32遇到的坑,你知道几个?
1、AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中2 1,意思是APB2接高速设备。 2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h专门控制外围器件的配置,也就是开关头文件的作用 3、HSE Osc(High Speed External Oscillator)高速外部晶振,一般为8MHz,HSI RC(High Speed InternalRC)高速内部RC,8MHz 4、LSE Osc(Low Speed External Oscillator)低速外部晶振,一般为32.768KHz,LSI RC(Low Speed InternalR
[单片机]
142条<font color='red'>STM32</font>遇到的坑,你知道几个?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved