找回密码
 立即注册
楼主: ercircle

分享USB_CDC库, USB_HID库, SDCC版, IAR版, @Ai8051U-8Bit

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:648
  • 最近打卡:2025-09-18 07:41:40

124

主题

2070

回帖

6282

积分

论坛元老

积分
6282
发表于 2025-2-21 10:38:26 | 显示全部楼层
谢谢分享!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 09:35:58 | 显示全部楼层
大佬,官方的  AI8051U.H  里面 有c51的语法,像下面这个  unsigned char volatile far   这个在sdcc里面对应的是啥,你知道不?

是不是  __sfr   __at(0x7efeb0)    PWMA_ETRPS  ?  好像不对。会报地址超出的问题。


#define     PWMA_ETRPS              (*(unsigned char volatile far *)0x7efeb0)
#define     PWMA_ENO                (*(unsigned char volatile far *)0x7efeb1)
#define     PWMA_PS                 (*(unsigned char volatile far *)0x7efeb2)
#define     PWMA_IOAUX              (*(unsigned char volatile far *)0x7efeb3)
#define     PWMB_ETRPS              (*(unsigned char volatile far *)0x7efeb4)
#define     PWMB_ENO                (*(unsigned char volatile far *)0x7efeb5)
#define     PWMB_PS                 (*(unsigned char volatile far *)0x7efeb6)
#define     PWMB_IOAUX              (*(unsigned char volatile far *)0x7efeb7)
#define     PWMA_PS2                (*(unsigned char volatile far *)0x7efeb8)
#define     PWMA_RCRH               (*(unsigned char volatile far *)0x7efeb9)
#define     PWMB_RCRH               (*(unsigned char volatile far *)0x7efeba)

#define     PWMA_CR1                (*(unsigned char volatile far *)0x7efec0)
#define     PWMA_CR2                (*(unsigned char volatile far *)0x7efec1)
#define     PWMA_SMCR               (*(unsigned char volatile far *)0x7efec2)
#define     PWMA_ETR                (*(unsigned char volatile far *)0x7efec3)
#define     PWMA_IER                (*(unsigned char volatile far *)0x7efec4)
#define     PWMA_SR1                (*(unsigned char volatile far *)0x7efec5)
#define     PWMA_SR2                (*(unsigned char volatile far *)0x7efec6)
#define     PWMA_EGR                (*(unsigned char volatile far *)0x7efec7)
#define     PWMA_CCMR1              (*(unsigned char volatile far *)0x7efec8)
#define     PWMA_CCMR2              (*(unsigned char volatile far *)0x7efec9)
#define     PWMA_CCMR3              (*(unsigned char volatile far *)0x7efeca)
#define     PWMA_CCMR4              (*(unsigned char volatile far *)0x7efecb)
#define     PWMA_CCER1              (*(unsigned char volatile far *)0x7efecc)
#define     PWMA_CCER2              (*(unsigned char volatile far *)0x7efecd)
#define     PWMA_CNTRH              (*(unsigned char volatile far *)0x7efece)
#define     PWMA_CNTRL              (*(unsigned char volatile far *)0x7efecf)
#define     PWMA_PSCRH              (*(unsigned char volatile far *)0x7efed0)
#define     PWMA_PSCRL              (*(unsigned char volatile far *)0x7efed1)
#define     PWMA_ARRH               (*(unsigned char volatile far *)0x7efed2)
#define     PWMA_ARRL               (*(unsigned char volatile far *)0x7efed3)
#define     PWMA_RCR                (*(unsigned char volatile far *)0x7efed4)
#define     PWMA_CCR1H              (*(unsigned char volatile far *)0x7efed5)
#define     PWMA_CCR1L              (*(unsigned char volatile far *)0x7efed6)
#define     PWMA_CCR2H              (*(unsigned char volatile far *)0x7efed7)
#define     PWMA_CCR2L              (*(unsigned char volatile far *)0x7efed8)
#define     PWMA_CCR3H              (*(unsigned char volatile far *)0x7efed9)
#define     PWMA_CCR3L              (*(unsigned char volatile far *)0x7efeda)
#define     PWMA_CCR4H              (*(unsigned char volatile far *)0x7efedb)
#define     PWMA_CCR4L              (*(unsigned char volatile far *)0x7efedc)
#define     PWMA_BKR                (*(unsigned char volatile far *)0x7efedd)
#define     PWMA_DTR                (*(unsigned char volatile far *)0x7efede)
#define     PWMA_OISR               (*(unsigned char volatile far *)0x7efedf)



点评

你看我发的源码里搜下,对应这个: #define PWMA_ETRPS (*(unsigned char volatile __xdata *)0xfeb0)  详情 回复 发表于 2025-2-23 10:46
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:302
  • 最近打卡:2025-09-18 08:50:50
已绑定手机

82

主题

3126

回帖

6929

积分

荣誉版主

无情的代码机器

积分
6929
发表于 2025-2-23 10:46:32 | 显示全部楼层
duro*** 发表于 2025-2-23 09:35
大佬,官方的  AI8051U.H  里面 有c51的语法,像下面这个  unsigned char volatile far   这个在sdcc里面对 ...

你看我发的源码里搜下,对应这个:
#define     PWMA_ETRPS              (*(unsigned char volatile __xdata *)0xfeb0)
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 11:27:01 | 显示全部楼层
erci*** 发表于 2025-2-23 10:46
你看我发的源码里搜下,对应这个:
#define     PWMA_ETRPS              (*(unsigned char volatile __x ...

刚刚重新看了一下。我知道了。多谢。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 11:36:15 | 显示全部楼层
我往你的工程里加了一个红外的,直接把你的工程搞崩了。

想要跟着你的步法,还是任重而道远。

截图202502231142337569.jpg

---------------------------------------------------------------------------------
                case VK_DIGIT_0:
                    // printf("00000000");      //在数码管上显示字符串
                    IrWave(rawDataAirOn1, sizeof(rawDataAirOn1) / sizeof(rawDataAirOn1[0]));
                    break;
                case VK_DIGIT_1:
                    // printf("%08lx", 0x1234abcdL);      //在数码管上显示字符串
                    IrWave(rawDataAirOn2, sizeof(rawDataAirOn2) / sizeof(rawDataAirOn2[0]));
                    break;
                case VK_DIGIT_2:
                    // SEG7_ShowLong(0x98765432, 16);     //在数码管上显示4字节长整型数
                    IrWave(rawDataAirOn3, sizeof(rawDataAirOn3) / sizeof(rawDataAirOn3[0]));
                    break;

-------------------------------------------------------------------------

#ifndef __IR_AIR_H__
#define __IR_AIR_H__

#include "ir_air.h"

#include "Ai8051U.h"

typedef     unsigned int    u16;

static volatile u16 tx_cnt;     //发送或空闲的脉冲计数(等于38KHZ的脉冲数,对应时间), 红外频率为38KHZ, 周期26.3us

void PWM_config(void)
{
    PWMA_CCER2 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道
    PWMA_CCMR4 = 0x60; //设置 PWM4 模式1 输出
//  PWMA_CCER2 = 0xB0; //使能 CC4E 通道, 低电平有效

    PWMA_ARRH = 0x02;  //设置周期时间
    PWMA_ARRL = 0x77;
    PWMA_CCR4H = 0;
    PWMA_CCR4L = 210;  //设置占空比时间

    PWMA_PS = 0x80;    //高级 PWM 通道 4N 输出脚选择位, 0x00:P1.7, 0x40:P0.7, 0x80:P2.7
//  PWMA_PS = 0x80;    //高级 PWM 通道 4P 输出脚选择位, 0x00:P1.6, 0x40:P0.6, 0x80:P2.6
    PWMA_ENO = 0x80;   //使能 PWM4N 输出
//  PWMA_ENO = 0x40;   //使能 PWM4P 输出
    PWMA_BKR = 0x80;   //使能主输出
//  PWMA_IER = 0x10;   //使能中断
    PWMA_CR1 |= 0x81;  //使能ARR预装载,开始计时
}

void PWMA_ISR() __interrupt(PWMA_VECTOR)
{
    if(PWMA_SR1 & 0X10)
    {
        PWMA_SR1 &=~0X10;
        // PWMA_SR1 = 0;
        if(--tx_cnt == 0)
        {
            PWMA_CCER2 = 0x00; // 写 CCMRx 前必须先清零 CCxE 关闭通道
            PWMA_CCMR4 = 0x40; // 设置 PWM4 强制为无效电平
            PWMA_CCER2 = 0x70; // 使能 CC4NE 通道, 低电平有效
            PWMA_IER = 0x00;   // 关闭中断
        }
    }
}

void IR_TxPulse(u16 pulse)
{
    tx_cnt = pulse;
    PWMA_CCER2 = 0x00; //
    PWMA_CCMR4 = 0x60; //
    PWMA_CCER2 = 0x70; //
    PWMA_IER = 0x10;   //
    while(tx_cnt);
}

void IR_TxSpace(u16 pulse)
{
    tx_cnt = pulse;
    PWMA_CCER2 = 0x00; //
    PWMA_CCMR4 = 0x40; //
    PWMA_CCER2 = 0x70; //
    PWMA_IER = 0x10;   //
    while(tx_cnt);
}

void IrWave(u16 *raw, int rawNum)
{
    int i;
    for(i = 0; i < rawNum; i++)
    {
        if (i % 2 == 0) {
            IR_TxPulse(raw/1000*38);
        } else {
            IR_TxSpace(raw/1000*38);
        }
    }
}

#endif

点评

夸张了,慢慢来呗搞不定了工程贴上来大家一块研究研究  详情 回复 发表于 2025-2-23 11:51
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:302
  • 最近打卡:2025-09-18 08:50:50
已绑定手机

82

主题

3126

回帖

6929

积分

荣誉版主

无情的代码机器

积分
6929
发表于 2025-2-23 11:51:09 | 显示全部楼层
duro*** 发表于 2025-2-23 11:36
我往你的工程里加了一个红外的,直接把你的工程搞崩了。

想要跟着你的步法,还是任重而道远。

夸张了,慢慢来呗搞不定了工程贴上来大家一块研究研究
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 12:25:47 | 显示全部楼层
erci*** 发表于 2025-2-23 11:51
夸张了,慢慢来呗搞不定了工程贴上来大家一块研究研究

USB-CDC_SDCC_IAR_Project.rar (112.08 KB, 下载次数: 54)


我增加了两个文件  Library/ir_air.c  Library/ir_air.h

其实 Library/ir_air.c 中只有  void IrWave(u16 *raw, int rawNum)  这个函数是我写的,其他的代码是我从官网的例子里 复制过来的。

从字面意思来看比较简单,就是 用 红外的 脉冲 和 空闲 两个函数把 main.c 中的 rawDataAirOn1 发出去。

然后在 User/Main.c 里面调用了一下。



#include "stdio.h"
#define PRINTF_HID        
//#define PRINTF_SEGLED //printf输出重定向到ISP下载软件中的7段数码管

#include "AI8051U.h"  //包含此头文件后,不需要再包含"reg51.h"头文件
#include "usb.h"     //USB调试及复位所需头文件
#include "vk.h"
#include "pic.h"
#include "string.h"
#include "ir_air.h"

#define MAIN_Fosc       24000000L   //定义主时钟

BYTE xdata cod[8];

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令

u16 rawDataAirOn1[197] = {6122, 7424,  514, 1674,  514, 1674,  514, 1676,  514, 1674,  514, 1674,  514, 1676,  512, 1676,  514, 1674,  514, 580,  514, 580,  514, 580,  514, 580,  514, 578,  514, 580,  514, 580,  514, 578,  514, 1676,  514, 1674,  514, 1674,  514, 1674,  514, 1676,  512, 1674,  514, 1674,  514, 1676,  514, 578,  514, 580,  514, 582,  512, 582,  512, 580,  514, 580,  514, 580,  514, 580,  514, 1676,  514, 1674,  514, 1674,  514, 1674,  514, 1676,  514, 1672,  514, 1674,  514, 1674,  514, 580,  512, 580,  514, 578,  514, 580,  512, 582,  514, 580,  514, 580,  514, 580,  514, 1674,  514, 580,  514, 1674,  514, 580,  514, 580,  514, 580,  512, 582,  514, 1676,  512, 580,  514, 1674,  514, 580,  514, 1676,  512, 1676,  512, 1674,  512, 1676,  512, 582,  514, 580,  512, 1676,  512, 1676,  536, 558,  534, 1654,  512, 582,  536, 1654,  534, 1652,  534, 1654,  536, 558,  534, 558,  534, 1654,  536, 558,  534, 1654,  534, 558,  534, 560,  534, 560,  536, 1652,  534, 562,  534, 1652,  514, 582,  512, 1676,  512, 582,  512, 582,  512, 1674,  536, 560,  512, 1674,  536, 560,  512, 1674,  512, 584,  512, 1676,  512, 1678,  512, 7408,  512};  


u16 rawDataAirOn2[227] = {3410, 1670,  408, 1258,  410, 1260,  408, 424,  408, 426,  408, 424,  410, 1258,  408, 426,  408, 424,  408, 1258,  432, 1236,  408, 424,  430, 1236,  408, 426,  408, 424,  408, 1258,  408, 1258,  432, 402,  408, 1260,  408, 1258,  408, 426,  408, 424,  408, 1260,  408, 424,  408, 424,  408, 1258,  408, 424,  408, 426,  430, 404,  430, 402,  408, 424,  408, 426,  408, 426,  430, 402,  408, 426,  408, 426,  430, 402,  430, 402,  408, 426,  408, 426,  408, 426,  408, 426,  408, 426,  430, 1236,  430, 404,  408, 424,  408, 1260,  430, 404,  408, 424,  408, 1260,  408, 1260,  430, 404,  430, 404,  430, 402,  430, 404,  430, 402,  430, 402,  430, 402,  430, 1236,  408, 1260,  430, 404,  430, 402,  430, 402,  430, 404,  430, 404,  430, 402,  430, 1236,  430, 402,  430, 1238,  430, 1236,  430, 1236,  430, 404,  430, 404,  430, 404,  430, 402,  430, 404,  430, 404,  430, 404,  430, 404,  430, 404,  430, 404,  430, 402,  430, 404,  430, 402,  430, 404,  430, 404,  430, 404,  430, 402,  430, 402,  430, 404,  430, 404,  430, 404,  406, 426,  430, 404,  430, 402,  428, 404,  428, 404,  430, 404,  430, 404,  430, 404,  430, 404,  428, 404,  428, 404,  430, 404,  430, 404,  430, 404,  406, 426,  430, 1236,  430, 1238,  430, 1238,  430, 1236,  408, 1260,  430, 404,  406};  


u16 rawDataAirOn3[227] = {3492, 1746,  458, 1310,  462, 372,  460, 374,  460, 372,  460, 1312,  460, 396,  436, 398,  434, 400,  436, 1310,  460, 398,  436, 374,  460, 398,  434, 1312,  460, 398,  434, 398,  434, 398,  434, 1314,  458, 398,  436, 398,  436, 398,  436, 1312,  460, 372,  460, 374,  460, 400,  434, 1310,  460, 400,  434, 398,  434, 374,  460, 1310,  460, 398,  434, 374,  460, 372,  460, 1312,  460, 372,  460, 374,  460, 372,  460, 1310,  462, 370,  460, 374,  460, 374,  460, 374,  460, 374,  460, 1310,  460, 374,  460, 374,  460, 1312,  460, 374,  460, 372,  460, 1310,  460, 1312,  460, 372,  460, 372,  460, 374,  460, 372,  460, 374,  460, 374,  460, 374,  458, 1312,  460, 1310,  460, 372,  460, 374,  460, 372,  460, 374,  460, 372,  460, 374,  460, 1312,  482, 350,  482, 1290,  482, 352,  482, 350,  484, 350,  490, 370,  462, 372,  458, 376,  456, 376,  458, 376,  456, 374,  456, 376,  458, 376,  456, 376,  456, 376,  456, 376,  456, 376,  456, 376,  456, 376,  456, 378,  456, 378,  456, 378,  456, 378,  454, 402,  430, 402,  408, 426,  430, 404,  408, 426,  408, 426,  408, 426,  408, 426,  408, 424,  408, 426,  430, 378,  454, 378,  456, 378,  456, 376,  456, 376,  456, 374,  458, 376,  458, 1314,  458, 1314,  458, 374,  456, 376,  458, 376,  458, 1314,  456};  

//P3.2口按键复位所需变量
bit Key_Flag;
u16 Key_cnt;

void sys_init();
void delay_ms(u8 ms);
void KeyResetScan(void);
// PUTCHAR_FUN(){
//         USB_SendData((BYTE*)&c,1);
//         return c;
// }
void main()
{
    sys_init();
    usb_init();
    PWM_config();

    EA = 1;
   
    while (1)
    {
        delay_ms(1);
        KeyResetScan();   //长按P3.2口按键触发软件复位,进入USB下载模式,不需要此功能可删除本行代码

        if(DeviceState != DEVSTATE_CONFIGURED)  //判断USB设备是否配置完成
            continue;

        if (bUsbOutReady)
        {
            if ((UsbOutBuffer[0] == 'K') &&
                (UsbOutBuffer[1] == 'E') &&
                (UsbOutBuffer[2] == 'Y') &&
                (UsbOutBuffer[3] == 'P'))
            {
                switch (UsbOutBuffer[5])
                {
                case VK_DIGIT_0:
                    // printf("00000000");      //在数码管上显示字符串
                    IrWave(rawDataAirOn1, sizeof(rawDataAirOn1) / sizeof(rawDataAirOn1[0]));
                    break;
                case VK_DIGIT_1:
                    // printf("%08lx", 0x1234abcdL);      //在数码管上显示字符串
                    IrWave(rawDataAirOn2, sizeof(rawDataAirOn2) / sizeof(rawDataAirOn2[0]));
                    break;
                case VK_DIGIT_2:
                    // SEG7_ShowLong(0x98765432, 16);     //在数码管上显示4字节长整型数
                    IrWave(rawDataAirOn3, sizeof(rawDataAirOn3) / sizeof(rawDataAirOn3[0]));
                    break;

---------------------------------------------------------------------------------------------------------



回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 12:32:15 | 显示全部楼层

void IrWave(u16 *raw, int rawNum)
{
    int i;
    for(i = 0; i < rawNum; i++)
    {
        if (i % 2 == 0) {
            IR_TxPulse(raw/1000*38);    //  我简单解释一下为啥要除以1000,这个是把us转成ms,成以38是我发现官网的例子里似乎是把毫秒乘以38才往出发。
        } else {
            IR_TxSpace(raw/1000*38);
        }
    }
}

----------------------------------------------------
下面这段代码是官网给的例子里的,我分析了官网的代码,发现这个接口传的值应该是ms值*38
        if (KeyCode != 0)       //检测到键码
        {
            KeyCode=255;
            TxTime = 0;
            //一帧数据最小长度 = 9 + 4.5 + 0.5625 + 24 * 1.125 + 8 * 2.25 = 59.0625 ms
            //一帧数据最大长度 = 9 + 4.5 + 0.5625 + 8 * 1.125 + 24 * 2.25 = 77.0625 ms
            IR_TxPulse(342);    //对应9ms,同步头       9ms       这里的342 应该就是9 *38 得来的
            IR_TxSpace(171);    //对应4.5ms,同步头间隔 4.5ms  这里的171 应该就是4.5*38 得来的
            IR_TxPulse(21);     //开始发送数据          0.5625ms     这里的21 应该就是0.5625*38 得来的

            IR_TxByte(User_code%256);   //发用户码低字节
            IR_TxByte(User_code/256);   //发用户码高字节
            IR_TxByte(KeyCode);         //发数据
            IR_TxByte(~KeyCode);        //发数据反码

            if (TxTime < 56)    //一帧按最大77ms发送, 不够的话,补偿时间     108ms
            {
                TxTime = 56 - TxTime;
                TxTime = TxTime + TxTime / 8;
                delay_ms(TxTime);
            }

            delay_ms(31);

            while (IO_KeyState != 0) //键未释放
            {
                IR_TxPulse(342);    //对应9ms,   同步头        9ms
                IR_TxSpace(86);     //对应2.25ms,同步头间隔    2.25ms
                IR_TxPulse(21);     //开始发送数据              0.5625ms
                delay_ms(96);
                IO_KeyScan();
            }

            printf("User_code=0x%04X,KeyCode=%u\r\n", User_code, KeyCode);
            KeyCode = 0;
        }
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:302
  • 最近打卡:2025-09-18 08:50:50
已绑定手机

82

主题

3126

回帖

6929

积分

荣誉版主

无情的代码机器

积分
6929
发表于 2025-2-23 12:58:08 | 显示全部楼层
sdcc要在main函数所在文件声明中断中断才生效。和keil的差异点可以参考我这个帖子

【四合一】分享一个可同时编译Keil C251\Keil C51\SDCC\IAR工程模板 - SDCC, IAR C++ for 51, GCC, VSCode,Linux, MacOS 国芯技术交流网站 - AI32位8051交流社区
建议:
业务代码放在sdcc工程,不要放在lib工程,否则每次修改后要重新编译两个工程。
编译前clean缓存:
make clean
make

另外修改了几处可能是bug,你试下
截图202502231255002676.jpg
截图202502231254386435.jpg
截图202502231254487333.jpg

这两行验证不阻塞了:
截图202502231255567722.jpg
截图202502231255453633.jpg

USB-CDC_SDCC_IAR_Project.zip (732.54 KB, 下载次数: 73)
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-07-19 05:31:21

83

主题

692

回帖

1317

积分

金牌会员

积分
1317
发表于 2025-2-23 13:28:40 | 显示全部楼层
erci*** 发表于 2025-2-23 12:58
sdcc要在main函数所在文件声明中断中断才生效。和keil的差异点可以参考我这个帖子

【四合一】分享一个可同 ...

官网的例子里有个bug,我也往里面加了两个bug 。

1.extern void PWMA_ISR() __interrupt(PWMA_VECTOR);   //这个是我改出来的。
2.tx_cnt--; // 等于0的时候继续--,这个bug是官网原来的。
3.IR_TxPulse(raw/1000.0*38); // 这个除法的大bug 也是我搞出来的。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-9-18 20:27 , Processed in 0.141040 second(s), 99 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表