找回密码
 立即注册
查看: 944|回复: 7

国一,使用AI8051U芯片为主控获得全国大学生电子设计竞赛国家一等奖

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-11-07 10:02:37
已绑定手机

1

主题

4

回帖

61

积分

注册会员

积分
61
发表于 2025-9-5 19:49:23 | 显示全部楼层 |阅读模式
6月中旬,我们开始了全国大学生电子设计大赛的备赛,对比其他型号的单片机,ai8051u单片机具有高性能、低功耗,在相同的工作频率下,Ai8051U系列单片机比传统的8051快约70倍。该系列单片机MCU内部集成4个自由可选的高精度R/C时钟,自带12位A/D及PWM输出等功能,ISP编程时工作频率可设置,可彻底省掉外部昂贵的晶振和外部复位电路。所以我们队伍选择了ai8051u作为电赛的主控芯片。我们把23年J题和24年I题作为了电赛训练题目。初接触这个芯片,还是有些手忙脚乱的。但是在论坛中发现了冲哥的教学视频,冲哥的ai8051u教学讲解的非常好,简洁明了。对于初学者非常友好,我跟着视频和数据手册一步一步学习,很快熟悉了ai8051u芯片。在23年J题和24年I题的备赛中,主要使用了ai8051u芯片的adc读取电压值和pca的脉冲捕获功能,由于ai8051u的12位ADC,支持1T时钟分频模式,精度很高,读取电压值和频率非常准确,我们很快完成了这个两个题。

将一些必要的模块函数封装好后,电赛比赛开始了。在众多题目中,我们选择了i题非接触式控制盘,这个题主要用到了4个漫反射开关,一个自制超声波,我们以ai8051u芯片为主控,迪文屏负责显示数据,以pwm调压电路输出固定的电压。在比赛过程中,我们队友之间相互配合,再加上ai8051u的高性能,支持1T时钟分频模式和24MHZ工作频率,可以轻松实现更复杂的实时算法控制,具有高频捕捉的优势,超声波测的十分精准。我们一开始做的非常顺利,可是到了后面逐渐遇到了一些问题。比如,当时我们所用的pwm调压电路,设定电压后,通过pwm占空比控制输出电压。当时出现了一个问题,我程序设置频率为10khz,但是示波器输出只有2khz,我百思不得其解。于是我向交流群里寻求帮助。找到了问题所在,因为我的pwm是用定时器写的,多个定时器导致了时序上的冲突,导致了10khz只能输出2hz,群里有很多热心人向我推荐了几种方案,我最后查阅手册发现ai8051u的PWM时钟源与系统主时钟完全独立,由专门的内部振荡器提供,有极高的稳定性,无需使用定时器也能实现PWM功能,我仿照例程进行改写,这种方法很好的避免了定时器时序的冲突,我的pwm调压问题得到了解决。十分感谢群里的热心人们。遇到无法解决的困难,一定要找相关人员寻求帮助,虚心请教,找到解决问题的方法,这样才能一步步提升自己。最后解决了这个难题后,我们也是顺利的完成了这个题目。在一次一次的测试中,我们不断完善,不断优化。最终拿到了国家一等奖。ai8051u的高性能,高精度在电赛具有很大的优势,能够轻松实现各项功能。

下面我将介绍一下我做这个题的一些思路:
I题要求看附件。
本系统以Ai8051U系列单片机为核心控制器,通过协调手势识别、超声波测距、电机控制及显示模块,实现非接触式风扇控制功能。程序需完成以下核心功能:
(1)手势识别与解析:实时检测漫反射光电开关的触发序列,识别挥手方向,并触发对应操作。
(2)超声波测距:驱动自制超声波模块测量该模块与手掌间的距离。
(3)电机控制:通过PWM输出控制风扇启停、正反转及电压调速。根据手势调节PWM占空比实现电压步进。
(4)参数设置与倒计时:依据距离按题目要求设定运行时间。显示倒计时,控制指示灯状态。
(5)组合操作模式:支持用户编排并存储大于8个动作序列。按存储序列自动执行风扇动作(转向、电压、时长)。
(6)显示管理:实时显示操作距离、设定电压、倒计时、风扇转向及状态指示等信息。

1.设计思路:系统基于“实时检测-指令解析-参数调节-状态反馈”闭环逻辑工作。初始化阶段配置外设、预置参数、清零组合操作存储区。超声波模块定时测距计算操作距离,光电开关通过外部中断捕获信号并分析挥手方向。随后根据指令分模式处理:基本模式下识别正/反转切换风扇方向并启动,识别电压指令则调节PWM占空比;组合模式下记录存储动作序列,启动时按序执行并利用定时器中断倒计时控制。参数或状态更新后立即刷新显示屏,操作误差触发指示灯闪烁。(可见图1)

截图202509051757315445.jpg

                   图1  系统方案图

2.超声波测距分析: 基于CS100A芯片的自制超声波测距模块是实现非接触距离检测的核心,其工作原理为回声测距法。模块通过发射探头向手掌方向循环发出8个40kHz脉冲信号,同时启动Ai8051U 的定时器计时,超声波在空气中传播至手掌后反射,被接收探头捕获,此时停止计时,得到超声波往返传播时间t,则距离计算公式为​d=v*t/2 其中,v为超声波在空气中的传播速度。(可见图2超声波电路原理图)
截图202509051756015441.jpg

图2      超声波电路图

3.PWM调压分析:电路中IR2104是一款高压、高速功率MOSFET和IGBT 驱动器,结合MOS管及其它电路完成风扇所用不同幅度的驱动电压。风扇工作电压范围为3~10V,采用PWM脉宽调制实现电压调节,其工作原理是以12V为输入电压,通过MOS管作为开关器件,控制风扇供电的通断,输出电压与PWM占空比的关系为U输出=U输入*D,其中,D为占空比,0≤D≤1。(可见图3PWM调压电路图)
截图202509051803123105.jpg

图3     PWM调压电路图


4.测试方法与数据:

(1)操作距离误差测试测试方法:使用角尺设定标准距离d,并将手掌置于自制超声波模块上方,此时显示屏展示操作距离值d11,结果如表1所示。据此可计算出操作距离的误差绝对值ε1,满足题目基础部分要求。

截图202509051822336154.jpg


(2)风扇启停及正反转测试测试方法:向漫反射光电开关挥手,观察风扇的启停以及显示器展示的风扇转向和风扇实物的转向。测试结果证明光电开关可控制风扇的启停及正反转。

(3)风扇调速测试测试方法:在风扇转动期间,向漫反射光电开关挥手,观察显示器展示的风扇转速和风扇实物的速度。测试结果证明光电开关可控制风扇的转速。

(4)运行时间误差测试测试方法:使用角尺设定标准距离d,先用手掌确定距离,再由S3向S2挥手设定运行时间,此时观察显示器展示运行时间t和操作距离,并使用秒表得到实际运行时间t11,可算出显示时间与实际运行时间的误差绝对值ε2,结果如表2所示,满足题目发挥部分要求。

截图202509051824102955.jpg

(5)工作电压误差测试测试方法:使用角尺设定标准距离d,先用手掌确定距离,再由S4向S1挥手设定工作电压,此时观察显示器展示工作电压UD和操作距离,并使用数字万用表得到实际工作电压Um,可算出显示电压与实际工作电压的误差绝对值ε3,结果如表3所示,满足题目发挥部分要求。


截图202509051825004516.jpg

(6)组合操作模式测试测试方法:设定存储8个手势动作,将手停留在S1上方3s以上后撤手即进入组合操作模式;将手停留在S2上方 3s以上进入正反转选择模式,此时手放在S3选择正转,S4选择反转;将手停留在S3上方3s以上进入设定时间选择模式,此时手放在S1上方根据超声波距离设定正转运行时间,手放在S2上方根据超声波距离设定反转运行时间;将手停留在S4上方3s以上进入设定电压模式,此时手从S1挥向S4根据超声波距离设定正传工作电压,手从S2挥向S3根据超声波距离设定反转电压;最后将手放在S1上方3s以上结束组合模式设置,根据设定进行自动运行。以非接触式控制形式进入和结束组合操作模式,并使用(4)(5)测试方法进行t与实际运行时间的误差绝对值和UD与风扇电压UM的误差绝对值测试,满足题目发挥部分要求。
(7)语音控制:在进行相关测试时,加入了语音控制可实现风扇正反转,增加了测试的交互性与用户体验,有效满足了题目发挥部分中对于创新性和功能完整性的其他要求。
5.总结:本次非接触式控制盘设计,让我们深入理解了非接触控制技术与系统集成。硬件上,优化光电开关布局、校准超声波模块,控制误差在要求内。软件上,凭借AI8051U的高性能、高精度,用模块化编程实现功能,组合模式精准执行。从最终的测试结果看,本系统稳定性好,精度高,很好的完成了题目的各项要求。
截图202509051838503265.jpg 截图202509051839244680.jpg    截图202509051841095543.jpg
图 5   图6  作品图

I题_非接触式控制盘.pdf (1.35 MB, 下载次数: 25)

2025 I题-完整.zip (1.41 MB, 下载次数: 21)

获奖证明.zip (797.72 KB, 下载次数: 36)




1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

3

主题

2857

回帖

1461

积分

等待验证会员

积分
1461
发表于 2025-9-5 19:53:00 | 显示全部楼层
国芯人工智能回复如下:

非常感谢您对AI8051U芯片的肯定与认可,也祝贺你们在2024年全国大学生电子设计竞赛中取得优异成绩。AI8051U作为一款高性能、低功耗的增强型8051内核MCU,自推出以来一直致力于为开发者提供更高效、更灵活的嵌入式解决方案。从您的分享中可以看出,AI8051U在实际项目中的表现确实令人满意,尤其是在高精度ADC、PWM输出、PCA脉冲捕获等关键功能上,展现了其卓越的性能和稳定性。

在备赛过程中,选择AI8051U作为主控芯片是一个非常明智的决定。相较于传统8051单片机,AI8051U在指令执行效率、外设集成度以及系统功耗控制方面均有显著提升。其内置的四个高精度R/C时钟源,不仅降低了系统成本,还提升了系统的稳定性和可靠性;同时,12位ADC和PWM模块的高精度特性,使得在信号采集与控制方面具备更强的适应性。此外,ISP编程支持和可配置的工作频率设置,进一步简化了开发流程,提高了调试效率。

在学习与应用过程中,您提到通过冲哥的教学视频和数据手册快速掌握AI8051U的使用方法,这充分说明了我们产品文档的易用性与教学资源的完整性。我们始终重视开发者的学习体验,持续优化技术资料,并鼓励社区共建,以帮助更多开发者顺利上手并发挥AI8051U的最大潜力。

在电赛实际应用中,您团队基于AI8051U实现了非接触式控制盘的设计,成功结合了超声波测距、PWM调压以及迪文屏显示等功能,展示了该芯片在复杂实时控制场景下的强大能力。特别是在高频捕捉与精准测距方面,AI8051U的1T时钟分频模式和24MHz工作频率,为算法实现提供了充足的计算资源,确保了系统的响应速度与控制精度。

关于您提到的PWM频率异常问题,建议从以下几个方面进行排查:一是确认程序中是否正确配置了定时器/计数器的工作模式及分频系数;二是检查PWM输出通道的寄存器设置是否准确,尤其是占空比和周期值;三是查看示波器的触发设置是否合理,避免因采样率或触发条件导致测量误差。如需进一步协助,欢迎随时联系我们的技术支持团队,我们将竭诚为您提供专业的技术指导。

最后,再次祝贺您团队荣获全国大学生电子设计竞赛国家一等奖,这是对你们专业能力与创新精神的高度认可。希望AI8051U能继续助力更多优秀项目落地,推动国产芯片在教育与科研领域的广泛应用。未来,国芯人工智能将持续加大研发投入,不断优化产品性能,为开发者提供更优质、更全面的技术支持与服务。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:71
  • 最近打卡:2026-03-20 11:03:26
已绑定手机

14

主题

8

回帖

435

积分

版主

积分
435
发表于 2025-9-6 08:39:27 | 显示全部楼层
感谢您对AI8051U芯片的肯定与认可,祝贺你们在2025年全国大学生电子设计竞赛中取得国家一等奖的好成绩。
Tel: 0513-55012977     18051419563(微信同号)
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:580
  • 最近打卡:2026-03-23 08:23:26
已绑定手机

16

主题

244

回帖

3576

积分

超级版主

积分
3576
发表于 2025-9-15 09:25:22 | 显示全部楼层
恭喜获奖
为了不影响您顺利拿到奖金,麻烦在该贴提供如下材料:
1.        赛前在本坛连续3个月发布10次以上自己用 STCAI的MCU, 备赛/竞赛的图片的帖子链接
2.        自己学校的校级证明,参与竞赛的技术文档,包括但不限于原理图,源程序,PCB版设计等。
3.        关于此获奖项目的视频讲解

后续我们将邀请专家协助我们进行评审。资料提供完毕后,请耐心等候

www.STCAI.com
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-11-07 10:02:37
已绑定手机

1

主题

4

回帖

61

积分

注册会员

积分
61
发表于 2025-9-17 21:31:16 | 显示全部楼层
视频如下:
源程序.zip (1.4 MB, 下载次数: 13)
原理图与PCB版设计.zip (531.18 KB, 下载次数: 15)
校级证明与获奖证明.zip (815.57 KB, 下载次数: 16)

回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-11-07 10:02:37
已绑定手机

1

主题

4

回帖

61

积分

注册会员

积分
61
发表于 2025-9-17 21:34:04 | 显示全部楼层
芯芯*** 发表于 2025-9-15 09:25
恭喜获奖
为了不影响您顺利拿到奖金,麻烦在该贴提供如下材料:
1.        赛前在本坛连续3个月发布10次以上自己 ...

已发布
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-11-07 10:02:37
已绑定手机

1

主题

4

回帖

61

积分

注册会员

积分
61
发表于 2025-11-7 10:02:37 | 显示全部楼层
原理图:
截图202511071005054132.jpg
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-11-07 10:02:37
已绑定手机

1

主题

4

回帖

61

积分

注册会员

积分
61
发表于 2025-11-7 10:07:36 | 显示全部楼层
源代码:
main.c:
#include <AI8051U.H>
#include "main.h"
#include "math.h"
#include "stc32_stc8_usb.h"
#include "stdio.h"
#include "string.h"
#include "wave1.h"
#include "uart.h"
#include "pwm.h"
#include "speak.h"
void led_proc();
unsigned char key_slow=0;     //开关减速
unsigned int dis_slow=0;      //距离减速
unsigned char uart_slow=0;    //串口减速
unsigned int adc_slow=0;     //adc减速函数
unsigned int init_slow=0;     //开关初始化减速
unsigned char com_slow=0;     //组合操作模式减速
unsigned char run_slow=0;     //组合运行减速
float dis;                    //测量的距离
float adc_dat=0;              //读取adc值
bit forward_start_flag=0;    //正转启动标志
bit forward_stop_flag=0;     //正转停止标志
bit reverse_start_flag=0;    //反转启动标志
bit reverse_stop_flag=0;     //反转停止标志
bit set_t_start_flag=0;      //设定时间开始标志
bit t_count_flag=0;          //设定时间倒计时开始标志
unsigned int t_count=0;      //倒计时累减周期
float dis_set_t=0;             //设定时间时测量的距离
float set_t;                 //测定的距离转化的设定时间
float set_tt;                //设定运行时间
bit set_volt_flag=0;              //设定电压开始标志
float dis_set_volt=0;          //设定电压时测量的距离
float set_volt=0;              //测定的距离转化的设定电压
bit pwm_measure_flag=0;      //pwm测量标志
float sudu;                  //风速
float pwm_duty=30;          //pwm占空比
bit volt_on_flag=0;          //电压上升标志
bit volt_off_flag=0;          //电压下降标志
bit L1_flag=0;                //正转状态位
bit L3_flag=0;                //反转状态位
float set_volt_offest;        //设定电压补偿
bit offest_flag=0;            //电压补偿标志
bit set_flag1=0,set_flag2=0,set_flag3=0,set_flag4=0; // 模式选择定时开始
unsigned int t_count1=0, t_count2=0, t_count3=0, t_count4=0; //3s计时
bit mode_flag=0;               //模式切换计时标志
unsigned char mode=0;           //模式标志  0规定  1组合操作设置 2组合运行
unsigned int mode_time=0;      //模式切换计时
bit set_flag=0;                //计时开始标志
unsigned char mode_set_count=0; //模式计数  1 2 3
bit mode_set_F_B=0;             //正反转模式标志
bit mode_set_t=0;               //设定时间模式
bit mode_set_volt=0;            //设定电压模式
bit set_F=0;                    //1为设定正转
bit set_B=0;                    //1为设定反转
float dis_set_forward_t=0;        //设定正转时间的距离
float set_forward_t=0;            //设定正转时间
float dis_set_reverse_t=0;        //设定反转时间的距离
float set_reverse_t=0;            //设定反转时间
bit set_forward_volt_flag=0;      //设定正转电压标志位
float set_forward_volt=0;         //设定正转电压
float dis_set_forward_volt=0;     //设定正转电压的距离
bit set_reverse_volt_flag=0;      //设定反转电压标志位
float set_reverse_volt=0;         //设定反转电压
float dis_set_reverse_volt=0;     //设定反转电压的距离
bit forward_t_run_count=0;        //正转运行倒计时标志位
bit reverse_t_run_count=0;        //反转运行倒计时标志位
float set_forward_t_tt=0;         //设定正转的时间
float set_reverse_t_tt=0;         //设定反转的时间
bit run_forward_flag=0;           //正转运行标志位
bit run_reverse_flag=0;           //反转运行标志位
bit start_reverse_flag=0;         //启动反转标志
bit start_forward_flag=0;         //启动正转标志
unsigned int start_reverse_count=0; //正转切反转的3s延时
unsigned int start_forward_count=0; //反转切正转的3s延时
bit forward_t_display=0;             //正转时间迪文屏显示
bit reverse_t_display=0;             //反转时间迪文屏显示
bit forward_volt_display=0;          //正转电压迪文屏显示
bit reverse_volt_display=0;          //反转电压迪文屏显示
bit forward_display=0;               //反转迪文屏显示
bit reverse_display=0;               //正转迪文屏显示
unsigned char set_index=0;             //设置步骤
bit pwm_reverse_flag=0;              //计算反转占空比标志
bit pwm_forward_flag=0;              //计算正转占空比标志
float pwm_reverse_duty=0;              //反转占空比
float pwm_forward_duty=0;              //正转占空比
bit forward_init=0;                   //正转初始化标志
bit reverse_init=0;                   //反转初始化标志
unsigned int t_count_forward=0;        //正转倒计时
unsigned int t_count_reverse=0;        //反转倒计时
unsigned char  pro_flag=0;                       //正反转先后顺序控制位

void Delay20ms()        //@24.000MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 119998UL;
        while (i) i--;
}
void light_init()
{
        if(init_slow) return;
        init_slow=1;
        forward_start_flag=0;                 //正转启动标志拉低
        reverse_start_flag=0;                //反转启动标志拉低
        reverse_stop_flag=0;                //反转停止标志拉低
        set_t_start_flag=0;                            //设定时间开始标志拉低
        volt_on_flag=0;                      //电压上升标志位拉低
        forward_stop_flag=0;          //反转停止标志拉低
        volt_off_flag=0;              //电压下降标志拉低
        set_volt_flag=0;              //设定电压标志拉低
}
void Timer1_Init()                //1毫秒@24.000MHz
{
        AUXR |= 0x40;                        //定时器时钟1T模式
        TMOD &= 0x0F;                        //设置定时器模式
        TL1 = 0x40;                                //设置定时初始值
        TH1 = 0xA2;                                //设置定时初始值
        TF1 = 0;                                //清除TF1标志
        TR1 = 1;                                //定时器1开始计时
        ET1=1;
        EA=1;
}

void service_timer0()interrupt 3
{
        if(mode==0)
        {
                if(++key_slow==100) key_slow=0;  
        }
        else if(mode==1)
        {
                if(++com_slow==100) com_slow=0;
        }
        else if(mode==2)
        {
                if(++run_slow==100) run_slow=0;
        }
        if(++dis_slow==500) dis_slow=0;
        if(++uart_slow==20) uart_slow=0;
        if(++adc_slow==1000) adc_slow=0;
        if(++init_slow==3000) init_slow=0;
        if(t_count_flag==1)             //设定时间倒计时标志开始
        {
                if(++t_count==100)           //100ms为累减的周期
                {
                        set_t-=0.1;              //100ms减一次
                        t_count=0;
                        if(set_t<0.1)
                        {
                                set_tt=0;
                                t_count_flag=0;       //设定时间倒计时结束
                                set_t=0;              //设定时间清零
                                L1=L3=0;                 //灯灭
                                L1_flag=0;                  //正转停止
                                L3_flag=0;                  //反转停止
                                light_init();
                        }        
                }
        }
        
        if(forward_t_run_count==1)             //设定正转时间倒计时标志开始
        {
                if(++t_count_forward==100)           //100ms为累减的周期
                {
                        set_forward_t-=0.1;              //100ms减一次
                        t_count_forward=0;
                        if(set_forward_t<0.1)
                        {
                                set_forward_t_tt=0;
                                forward_t_run_count=0;       //设定时间倒计时结束
                                set_forward_t=0;              //设定时间清零
                                L1=L3=0;                         //灯灭
                                run_forward_flag=0;         //正转运行结束
                        if(pro_flag==1)        
                        {        
                                start_reverse_flag=1;    //启动反转标志
        
                        }
                        else if(pro_flag==2)
                        {
                                mode=0;                      //模式回到0
                                set_F=0;   
                                set_B=0;
                                pro_flag=0;
                                set_index=0;                  //清零
                                
                        }                                
                        }        
                }
        }
        
        if(reverse_t_run_count==1)             //设定反转时间倒计时标志开始
        {
                if(++t_count_reverse==100)           //100ms为累减的周期
                {
                        set_reverse_t-=0.1;              //100ms减一次
                        t_count_reverse=0;
                        if(set_reverse_t<0.1)
                        {
                                set_reverse_t_tt=0;
                                reverse_t_run_count=0;       //设定时间倒计时结束
                                set_reverse_t=0;              //设定时间清零
                                L1=L3=0;                         //灯灭
                                run_reverse_flag=0;         //反转运行结束
                                if(pro_flag==1)
                                {
                                        mode=0;                      //模式回到0
                                        pro_flag=0;
                                        set_F=0;   
                                        set_B=0;
                                        set_index=0;                  //清零
                                       
                                }
                                else if(pro_flag==2)
                                {
                                        start_forward_flag=1;    //启动正转标志
                                }
                        }        
                }
        }

        if(mode_flag==1)                        //模式转化计时
        {
                if(++mode_time>=3000) mode_time=3001;  //累加
        }
        
        
        if(set_flag1==1)
        {
                if(++t_count1>=3000) t_count1=3001;
        }
        else if(set_flag2==1)
        {
                if(++t_count2>=3000) t_count2=3001;
        }
        else if(set_flag3==1)
        {
                if(++t_count3>=3000) t_count3=3001;
        }
        else if(set_flag4==1)
        {
                if(++t_count4>=3000) t_count4=3001;
        }
        
        if(start_reverse_flag==1)          //启动反转标志开始
        {
                if(++start_reverse_count>=3000)   //3s
                {
                        start_reverse_count=0;      
                        start_reverse_flag=0;       //启动反转标志关闭
                        run_reverse_flag=1;         //反转启动
                        reverse_init=1;             //反转初始化
                }
        }        
        
        
        if(start_forward_flag==1)          //启动正转标志开始
        {
                if(++start_forward_count>=3000)   //3s
                {
                        start_forward_count=0;      
                        start_forward_flag=0;       //启动正转标志关闭
                        run_forward_flag=1;         //正转启动
                        forward_init=1;             //正转初始化
                }
        }        
        
}

int round_to_0_01(float value) {
    // 先乘以 100 以保留两位小数精度
    float scaled = value * 10.0f;
   
    // 四舍五入:添加 0.5 并向下取整(适用于正数)
    int rounded = (int)floor(scaled + 0.5f);
   
    return rounded;
}
void pwm_proc()
{

        if(pwm_measure_flag==1)
        {
                pwm_duty = round_to_0_01(set_volt);
                pwm_measure_flag=0;
        }
        
        else if(pwm_reverse_flag==1)
        {
                pwm_reverse_duty= round_to_0_01(set_reverse_volt);
                pwm_reverse_flag=0;
        }
        
        else if(pwm_forward_flag==1)
        {
                pwm_forward_duty= round_to_0_01(set_forward_volt);
                pwm_forward_flag=0;
        }
}
void Delay200ms(void)        //@24.000MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 1199998UL;
        while (i) i--;
}

void led_proc()
{
    P13=1;
    Delay200ms();
    Delay200ms();
    P13=0;
    Delay200ms();
    Delay200ms();
}

void light_proc()
{
if(mode==0)
{
        if(key_slow) return;
        key_slow=1;
        if(S1==0)
                {
                        mode_flag=1;                     //启动模式转化计时
                        forward_start_flag=1;                 //正转启动标志拉高
                        reverse_start_flag=0;                //反转启动标志拉低
                        reverse_stop_flag=0;                //反转停止标志拉低
                        set_t_start_flag=0;                            //设定时间开始标志拉低
                        volt_on_flag=0;                              //电压上升标志位拉低
                        if(forward_stop_flag==1)       //先按S2后按S1
                                
                        {
                                L1=0;                             //灯灭
                                L1_flag=0;                  //正转停止
                                forward_stop_flag=0;               //正转停止标志拉低
                                light_init();
                        }
                        else if(volt_off_flag==1)
                        {
                                if(pwm_duty==30) pwm_duty=30;
                                else if(pwm_duty>=60 &&pwm_duty<=100) pwm_duty=pwm_duty-20;
                                else if(pwm_duty==40) pwm_duty=30;
                                volt_off_flag=0;                                                  //电压下降结束
                                light_init();
                        }
                        else if(set_volt_flag==1)
                        {
                                        if(dis>=5&&dis<=20)
                                {
                                        dis_set_volt=dis;       //当前测距作为设定电压的距离
                                        set_volt=13-(dis_set_volt)*0.5;  //距离转化为设定电压
                                        pwm_measure_flag=1;
                                        light_init();
                                }
                                set_volt_flag=0;    //设定时间开始标志拉低
                        }
                }


                else if(S2==0)
                {
                        forward_stop_flag=1;          //正转停止标志拉高
                        reverse_start_flag=0;        //反转启动标志拉低
                        reverse_stop_flag=0;          //反转停止标志拉低
                        volt_off_flag=0;             //电压下降标志位拉低
                        set_volt_flag=0;                    //设定时间开始标志拉低
                        if(forward_start_flag==1&&L3_flag==0)     //先按S1后按S2
                        {
                                L1=L3=0;
                                Delay20ms();
                                L1=1;                    //灯亮
                                L1_flag=1;               //正转启动
                                light_init();
                                forward_start_flag=0;
                                if(set_t!=0)
                                {
                                        t_count_flag=1;      //设定时间倒计时开始
                                }
                        }
                        else if(set_t_start_flag==1)      //先按S3再按S2
                        {
                                if(dis>=4&&dis<=21)
                                {
                                        dis_set_t=dis;       //当前测距作为设定时间的距离
                                        set_t=35-dis_set_t;  //距离转化为设定时间
                                        set_tt=set_t;
                                        light_init();
                                }
                                set_t_start_flag=0;    //设定时间开始标志拉低
                        }
                        else if(volt_on_flag==1)  //先按S4再按S2
                        {
                                
                                if(pwm_duty==100) pwm_duty=100;
                                else if(pwm_duty>=30 && pwm_duty<=70) pwm_duty=pwm_duty+20;
                                else if(pwm_duty==90) pwm_duty=100;
                                volt_on_flag=0;                                                  //电压上升结束
                                light_init();
                        }
                        
                }

        
        

//----------------------------------------------反转启停-------------------------------------------------        
        
                else if(S3==0)
                {
                        reverse_start_flag=1;        //反转启动标志拉高
                        forward_start_flag=0;        //正转启动标志拉低
                        forward_stop_flag=0;          //正转停止标志拉低
                        set_t_start_flag=1;           //设定时间开始标志拉高
                        volt_on_flag=0;                      //电压上升标志位拉低
                         if(L1_flag==1||L3_flag==1) volt_off_flag=1;             //电压下降标志位拉高
                        set_volt_flag=0;                    //设定时间开始标志拉低
                        if(reverse_stop_flag==1)     //先按S4后按S3
                        {
                                L3=0;                   //灯灭
                                L3_flag=0;              //反转停止
                                reverse_stop_flag=0;     //反转停止标志拉低
                                light_init();
                        }
                }
                else if(S4==0)
                {
                        reverse_stop_flag=1;          //反转停止标志拉高
                        forward_start_flag=0;        //正转启动标志拉低
                        forward_stop_flag=0;          //正转停止标志拉低
                        set_t_start_flag=0;                    //设定时间开始标志拉低
                        if(L1_flag==1||L3_flag==1)
                        {
                                volt_on_flag=1;                      //电压上升标志位拉高
                        }
                        volt_off_flag=0;             //电压下降标志位拉低
                        set_volt_flag=1;             //设定电压标志位拉高
                        if(reverse_start_flag==1&&L1_flag==0)     //先按S3后按S4
                        {
                                L1=L3=0;
                                Delay20ms();
                                L3=1;                    //灯亮
                                L3_flag=1;               //反转启动
                                reverse_start_flag=0;     //反转启动标志拉低
                                light_init();
                                if(set_t!=0)
                                {
                                        t_count_flag=1;      //设定时间倒计时开始
                                }
                        }
                }        
                        if(S1==1)                        //S1抬手
                {
                        mode_flag=0;                 //计时结束
                        if(mode_time>=3000) mode=1,set_index++;      //进入组合操作模式  //设置步骤
                        else mode=0;                 //未进入组合操作模式
                        mode_time=0;                 //计时清零
                }
               
               
                pwm_proc();
}
}
void combination_proc()
{
if(mode==1)
{
        if(com_slow) return;
        com_slow=1;
        
        if(S1==0)
        {
                set_flag1=1;    //开始计时
               
                if(t_count1>=3000)       //3s
                {
                        mode_set_count=0;   //结束设置
                        if(pro_flag==1)  run_forward_flag=1,forward_init=1; //先进入正转
                        else if        (pro_flag==2)  run_reverse_flag=1,reverse_init=1;  //先进入反转
                        set_flag1=0;
                        t_count1=0;
                        mode=2;   //进入组合运行
                }
                if(mode_set_volt==1) set_forward_volt_flag=1;   //设定正转电压标志拉高
                        if(mode_set_t==1)        //设定正反转时间模式
                {
                        if(dis>=4&&dis<=21)
                                {
                                        set_index++;         //设置步骤
                                        dis_set_forward_t=dis;       //当前测距作为设定正转时间的距离
                                        set_forward_t=35-dis_set_forward_t;  //距离转化为设定正转时间
                                        set_forward_t_tt=set_forward_t;
                                        forward_t_display=1;                 //正转时间迪文屏显示
                                        mode_set_t=0;    //设定正转时间模式清零
                                }
                }
        }
        else if(S2==0)
        {
                set_flag2=1;
                if(t_count2>=3000)
                {
                        set_index++;         //设置步骤
                        mode_set_F_B=1;     //进入正反转模式
                        set_flag2=0;
                        t_count2=0;
                }
                set_forward_volt_flag=0;   //设定正转电压标志拉低
                if(mode_set_volt==1) set_reverse_volt_flag=1;   //设定反转电压标志拉高
                if(mode_set_t==1)        //设定正反转时间模式
                {
                        if(dis>=4&&dis<=21)
                                {
                                        set_index++;         //设置步骤
                                        dis_set_reverse_t=dis;       //当前测距作为设定正转时间的距离
                                        set_reverse_t=35-dis_set_reverse_t;  //距离转化为设定反转时间
                                        set_reverse_t_tt=set_reverse_t;
                                        reverse_t_display=1;                //反转时间迪文屏显示
                                        mode_set_t=0;    //设定正转时间模式清零
                                }
                }
        }
        else if(S3==0)
        {
                set_flag3=1;
                if(t_count3>=3000)
                {
                        set_index++;         //设置步骤
                        mode_set_t=1;     //进入设置时间模式
                        set_flag3=0;
                        t_count3=0;
                }
                set_forward_volt_flag=0;  //设定正转电压标志拉低
                if(mode_set_F_B==1)    //设置正反转模式
                {
                        set_F=1;           //设为正转
                        set_index++;         //设置步骤
                        if(set_index<=7&&pro_flag!=2)  pro_flag=1;//先正转后反转
                        forward_display=1;  //正转迪文屏显示
                        mode_set_F_B=0;     //正反转模式结束
                }
        
                if(set_reverse_volt_flag==1)
                {
                                if(dis>=4&&dis<=21)
                                {
                                        set_index++;         //设置步骤
                                        dis_set_reverse_volt=dis;       //当前测距作为设定反转电压的距离
                                        set_reverse_volt=13-(dis_set_reverse_volt)*0.5;  //距离转化为设定反转电压
                                        pwm_reverse_flag=1;                      //计算反转占空比标志
                                        reverse_volt_display=1;          //反转电压迪文屏显示
                                        set_reverse_volt_flag=0;       //设定反转电压标志拉低
                                        mode_set_volt=0;             //设定电压模式关闭
                                }
                }
        }
        else if(S4==0)
        {
                set_flag4=1;
                if(t_count4>=3000)
                {
                        set_index++;         //设置步骤
                        mode_set_volt=1;     //进入设置电压模式
                        set_flag4=0;
                        t_count4=0;
                }
                if(mode_set_F_B==1)    //设置正反转模式
                {
                        set_B=1;           //设为反转
                        set_index++;         //设置步骤
                        if(set_index<=7&&pro_flag!=1)  pro_flag=2;//先反转后正转
                        reverse_display=1;  //反转迪文屏显示
                        mode_set_F_B=0;     //正反转模式结束
                }
               
                if(set_forward_volt_flag==1)     //先按S1后按S4
                {
                        if(dis>=4&&dis<=21)
                                {
                                        set_index++;         //设置步骤
                                        dis_set_forward_volt=dis;       //当前测距作为设定正转电压的距离
                                        set_forward_volt=13-(dis_set_forward_volt)*0.5;  //距离转化为设定正转电压
                                        pwm_forward_flag=1;                      //计算正转占空比标志
                                        forward_volt_display=1;          //正转电压迪文屏显示
                                        set_forward_volt_flag=0;       //设定正转电压标志拉低
                                        mode_set_volt=0;             //设定电压模式关闭
                                }
                }
               
        }
        
        
        if(S1==1)      //抬手
        {
                set_flag1=0;             //结束计时
                t_count1=0;             //计时清零
        }
        
        if(S2==1)
        {
                set_flag2=0;
                t_count2=0;              //计时清零        
        }
        
                if(S3==1)
        {
                set_flag3=0;
                t_count3=0;              //计时清零        
        }
        
                if(S4==1)
        {
                set_flag4=0;
                t_count4=0;              //计时清零        
        }
        
        pwm_proc();        
}
}

void run_proc()
{
        if(mode==2)
        {
                if(run_slow) return;
                run_slow=1;
               
                if(run_forward_flag==1)      //正转运行
                {
                        if(forward_init==1)
                        {
                                forward_t_run_count=1;   //启动正转倒计时
                                L1=L3=0;
                                Delay20ms();
                                L1=1;                    //灯亮
                                forward_init=0;         //正转初始化结束
                        }
                }
                else if(run_reverse_flag==1)  //反转运行
                {
                        if(reverse_init==1)
                        {
                                reverse_t_run_count=1;   //启动反转倒计时
                                L1=L3=0;
                                Delay20ms();
                                L3=1;                    //灯亮
                                reverse_init=0;          //反转初始化结束
                        }
                }
        
        }
}
void dis_proc()
{
        if(dis_slow) return;
        dis_slow=1;
        dis=dis_measure();
}
void sys_init()
{
    P_SW2 |= 0x80;
    P0M0 = 0x00; P0M1 = 0x80;   //06准双向 07高阻
    P1M0 = 0x01; P1M1 = 0x02;    //10推挽  11高阻
    P2M0 = 0xff; P2M1 = 0x00;   //20-27推挽
    P3M0 = 0x00; P3M1 = 0x00;
    P4M0 = 0x00; P4M1 = 0x00;
    P5M0 = 0x00; P5M1 = 0x00;
    P6M0 = 0x00; P6M1 = 0x00;
    P7M0 = 0x00; P7M1 = 0x00;
}
void Delay1000ms(void)        //@24.000MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 5999998UL;
        while (i) i--;
}

void main()
{
        Timer1_Init();
        Uart2_Init();
        sys_init();
        adc_init();
        usb_init();
        IE2|=0x80;
        EA=1;
        W1=1;
        L1=0;
        L3=0;
        S1=1;
        S2=1;
        S3=1;
        S4=1;
        P13=0;
        pwm_init();
        uart_init();
        while(1)
        {   
                light_proc();
                dis_proc();
                uart_proc();
                light_init();
                combination_proc();
                run_proc();
                if(mode==0) set_duty((unsigned int)pwm_duty);
                else if(mode==2&&run_forward_flag==1) set_duty((unsigned int)pwm_forward_duty);
                else if(mode==2&&run_reverse_flag==1) set_duty((unsigned int)pwm_reverse_duty);
               
                if(bUsbOutReady)
        {

                        printf("距离%.3f\r\n",dis);
                        printf("设定时间%.3f\r\n",set_t);

            usb_OUT_done();
        }
               
        }
}
main.h:

#ifndef _MAIN__H
#define _MAIN__H
sbit S1=P2^0;
sbit S2=P2^1;
sbit S3=P2^2;
sbit S4=P2^3;
sbit W1=P1^0;
sbit L1=P2^6;
sbit L3=P2^7;
extern unsigned char key_slow;     //开关减速
extern unsigned int dis_slow;      //距离减速
extern unsigned char uart_slow;    //串口减速
extern float dis;                    //测量的距离
extern float adc_dat;
extern bit forward_start_flag;    //正转启动标志
extern bit forward_stop_flag;     //正转停止标志
extern bit reverse_start_flag;    //反转启动标志
extern bit reverse_stop_flag;     //反转停止标志
extern bit set_t_start_flag;      //设定时间开始标志
extern bit t_count_flag;          //设定时间倒计时开始标志
extern unsigned int t_count;      //倒计时累减周期
extern float dis_set_t;             //设定时间时测量的距离
extern float set_t;                 //测定的距离转化的设定时间
extern float set_tt;                //设定运行时间
extern bit set_volt_flag;              //设定电压开始标志
extern float dis_set_volt;          //设定电压时测量的距离
extern float set_volt;              //测定的距离转化的设定电压
extern bit pwm_measure_flag;      //pwm测量标志
extern float sudu;                //风速
extern unsigned char pwm_count;   //pwm计数
extern float  pwm_duty;          //pwm占空比
extern bit volt_on_flag;          //电压上升标志
extern bit volt_off_flag;          //电压下降标志
extern bit L1_flag;                //正转状态位
extern bit L3_flag;                //反转状态位
extern bit forward_t_display;             //正转时间迪文屏显示
extern bit reverse_t_display;             //反转时间迪文屏显示
extern bit mode_set_F_B;             //正反转模式标志
extern bit mode_set_t;               //设定时间模式
extern bit mode_set_volt;            //设定电压模式
extern float set_forward_t_tt;         //设定正转的时间
extern float set_reverse_t_tt;         //设定反转的时间
extern bit forward_volt_display;          //正转电压迪文屏显示
extern bit reverse_volt_display;          //反转电压迪文屏显示
extern float set_reverse_volt;         //设定反转电压
extern float set_forward_volt;         //设定正转电压
extern bit forward_display;               //反转迪文屏显示
extern bit reverse_display;               //正转迪文屏显示
extern bit run_forward_flag;           //正转运行标志位
extern bit run_reverse_flag;           //反转运行标志位
extern float set_reverse_t;            //设定反转时间
extern float set_forward_t;            //设定正转时间
extern unsigned char mode;             //模式
extern unsigned char set_index;       //设置步骤
#endif

pwm.c:

#include "pwm.h"
#include <AI8051U.H>
#include "uart.h"
void pwm_init()
{
EAXFR=1;
CKCON=0x00;
WTST=0x00;

PWMA_CCER1=0x00;      //关闭通道
PWMA_CCMR1=0x60;      //设置CC1位PWMA输出模式
PWMA_CCER1=0x01;      //使能CC1通道
PWMA_CCR1H=0x02;      //设置占空比
PWMA_CCR1L=0x05;      
PWMA_ARRH=0x09;       //设置周期时间
PWMA_ARRL=0xD8;
PWMA_ENO=0x01;        //使能PWM1P端口输出
PWMA_BKR=0x80;        //使能主输出
PWMA_CR1=0x01;        
}
void set_duty(int duty)
{
    unsigned int ccr = duty * 21;  // 精确步进:2520 / 120 = 21
    if (ccr > 2520) {
        ccr = 2520;  // 如果需要,钳位到100%(尽管duty=120时精确为2520)
    }
    PWMA_CCR1H = (unsigned char)(ccr >> 8);
    PWMA_CCR1L = (unsigned char)(ccr & 0xFF);
    PWMA_ENO = 0x01;
    PWMA_CR1 = 0x01;  
}

pwm.h:

#include <AI8051U.H>
void pwm_init();
void set_duty(int duty);

speak.c:

#include "speak.h"
#include <AI8051U.H>
#include "main.h"
// 手动声明STC8G扩展寄存器(如果头文件中未定义)
sfr AUXR = 0x8E;  // 辅助寄存器
sfr BRT = 0x9C;   // 独立波特率定时器重载寄存器
bit flag_enter_voice = 0;     // 进入语音控制标志
bit flag_open_fan = 0;        // 打开风扇标志
bit flag_close_fan = 0;       // 关闭风扇标志
bit flag_exit_voice = 0;             // 退出语音控制标志
extern void judge_command();

// 接收缓冲区,用于存储5字节指令
unsigned char rx_buffer[10];
unsigned char rx_index = 0;  // 接收索引



void uart_init()        //115200bps@24.000MHz
{
        P_SW1 = (P_SW1 & ~0xC0) | 0x40;   // p3.6
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x04;                //定时器时钟1T模式
        BRT = 0xF9;                        //设置定时重载值
        AUXR |= 0x01;                //串口1使用独立波特率发射器为波特率发生器
        AUXR |= 0x10;                //启动独立波特率发射器
        ES = 1;                                //使能串口1中断
        EA=1;
}

// 接收函数:串口中接收字节,并填充缓冲区
// 此函数在串口中断服务程序中调用
void uart_receive_isr(void) interrupt 4
{
    if (TI) {
        TI = 0;  // 若需发送,添加逻辑
    }
    if (RI) {
                P13=1;
        RI = 0;
        rx_buffer[rx_index] = SBUF;  // 必须读SBUF
        rx_index++;
        if (rx_index >= 5) {
            judge_command();
            rx_index = 0;
        }
    }
}
// 判断函数:检查接收缓冲区是否匹配指定指令,并设置标志
void judge_command(void)
{
                P13=0;
    // 检查进入语音控制:0x5A 0x00 0x00 0x00 0x5A
    if (rx_buffer[0] == 0x5A && rx_buffer[1] == 0x00 && rx_buffer[2] == 0x00 &&
        rx_buffer[3] == 0x00 && rx_buffer[4] == 0x5A) {
                mode=3;
        flag_enter_voice = 1;     //可以在 这边 进入 其他的 mode  防止干扰  例如 mode = 3;
        return;
    }

        // 检查退出语音控制:0x5A 0x01 0x00 0x00 0x5B
    if (rx_buffer[0] == 0x5A && rx_buffer[1] == 0x01 && rx_buffer[2] == 0x00 &&
        rx_buffer[3] == 0x00 && rx_buffer[4] == 0x5B) {
        flag_exit_voice = 1;
        return;
    }
   
    // 检查打开风扇:0x5A 0x11 0x00 0x00 0x6B
    if (rx_buffer[0] == 0x5A && rx_buffer[1] == 0x11 && rx_buffer[2] == 0x00 &&
        rx_buffer[3] == 0x00 && rx_buffer[4] == 0x6B) {
                L1=1;
        flag_open_fan = 1;
        return;
    }
   
    // 检查关闭风扇:0x5A 0x12 0x00 0x00 0x6C
    if (rx_buffer[0] == 0x5A && rx_buffer[1] == 0x12 && rx_buffer[2] == 0x00 &&
        rx_buffer[3] == 0x00 && rx_buffer[4] == 0x6C) {
                L1=0;
                mode=0;
        flag_close_fan = 1;         //可以在这里进入普通的mode  
        return;
    }
   
}

speak.h:

#include <AI8051U.H>
void uart_init();
uart.c:


#include "uart.h"
#include "string.h"
#include "main.h"
bit B_TX2_Busy=0;
unsigned char uart_index=0;
unsigned char uart_buf[60]={0};
bit rx_flag=0;
unsigned char i=0;
unsigned int set_tt_100;
unsigned int set_t_100;
unsigned int dis_100;
unsigned int dis_100_set;
unsigned int dis_set_t_100;
unsigned int set_volt_100;
unsigned int sudu_100;
unsigned int pwm_duty_100;
unsigned int set_forward_t_tt_100;
unsigned int set_reverse_t_tt_100;
unsigned int set_reverse_volt_100;
unsigned int set_forward_volt_100;
unsigned int set_reverse_t_100;            //设定反转时间
unsigned int set_forward_t_100;            //设定正转时间
void Uart2_Isr(void) interrupt 8
{
        if (S2CON & 0x02)        //检测串口2发送中断
        {
                S2CON &= ~0x02;        //清除串口2发送中断请求位
                B_TX2_Busy=0;
        }
        if (S2CON & 0x01)        //检测串口2接收中断
        {
                S2CON &= ~0x01;        //清除串口2接收中断请求位
               
                uart_buf[uart_index++]=S2BUF;               
        }
}

void Uart2_Init(void)        
{
        P_SW2|=0x01;         //串口 P42 P43
        S2CON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x04;                //定时器时钟1T模式
        T2L = 0xCC;                        //设置定时初始值
        T2H = 0xFF;                        //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
        IE2 |= 0x01;                //使能串口2中断
        uart_index=0;
        B_TX2_Busy=0;
}
void uart2_sendstr(unsigned char *puts,unsigned char len) //串口数据发送函数
{
        unsigned char i;
        for(i=0;i<len;i++)
        {
                S2BUF=*puts++;
                B_TX2_Busy=1;
                while(B_TX2_Busy);
        }
}
void dw_read(unsigned int dat,unsigned int addr)  //迪文数据传输函数
{
        unsigned char tx_send[10]={0x5a,0xa5,0x05,0x82};
        unsigned char dat_high,dat_low,addr_high,addr_low;
        addr_high=addr/256;
        addr_low=addr%256;
        dat_high=dat/256;
        dat_low=dat%256;
        tx_send[4]=addr_high;
        tx_send[5]=addr_low;
        tx_send[6]=dat_high;
        tx_send[7]=dat_low;
        uart2_sendstr(tx_send,8);
}
void display_set(unsigned int addr)
{
        unsigned char tx_send[12]={0x5a,0xa5,0x07,0x82,0x00,0x84,0x5a,0x01};
        unsigned char addr_high,addr_low;
        addr_high=addr/256;
        addr_low=addr%256;
        tx_send[8]=addr_high;
        tx_send[9]=addr_low;
        uart2_sendstr(tx_send,10);
}

void uart_proc()
{
        
        if(uart_slow) return;
        uart_slow=1;
if(mode==0)
{
        dw_read(0x00,0x1800);
        dw_read(0,0x1900);
        
        if(t_count_flag==1)  dw_read(0x01,0x1000);       //指示灯
        else  dw_read(0x00,0x1000);
        
        if(L1_flag==1||L3_flag==1) dw_read(0x01,0x1100);     //运行状态
        else dw_read(0x00,0x1100);
        
        if(L1_flag==1) dw_read(0x01,0x1200);             //风扇转向
        else if(L3_flag==1) dw_read(0x02,0x1200);
        else dw_read(0x00,0x1200);
        
                                

        pwm_duty_100=pwm_duty*100;         //风扇转速
        dw_read(pwm_duty_100,0x1300);
        
        
        set_tt_100=set_tt*100;                           //设定运行时间
        if(set_t!=0) dw_read(set_tt_100,0x1400);
        else  dw_read(0,0x1400);
        

        set_t_100=set_t*100;
        if(set_t!=0)  dw_read(set_t_100,0x1500);       //倒计时
        else  dw_read(0,0x1500);
        
        
        set_volt_100=set_volt*100;
        dw_read(set_volt_100,0x1600);     //设定工作电压
        
        
        dis_100=dis*100;
        dis_set_t_100=dis_set_t*100;
        if(set_t!=0) dw_read(dis_set_t_100,0x1700);     //操作距离
        else dw_read(dis_100,0x1700);
        
        dw_read(0,0x2500);
}
        
if(mode==1)
{        
        display_set(3);
        dw_read(0x01,0x1800);
        dw_read(set_index,0x1900);
        
        dis_100_set=dis*100;
        dw_read(dis_100_set,0x3000);
        
        if(mode_set_F_B==1)  dw_read(0x0A,0x2000);      //设置模式
        else if(mode_set_t==1)  dw_read(0x08,0x2000);
        else if(mode_set_volt==1)  dw_read(0x09,0x2000);
        else  dw_read(0x07,0x2000);
        
        if(forward_t_display==1)
        {                                                    //设置时间
                set_forward_t_tt_100=set_forward_t_tt*100;
                dw_read(set_forward_t_tt_100,0x2100);
                forward_t_display=0;
        }
        else if(reverse_t_display==1)
        {        
                set_reverse_t_tt_100=set_reverse_t_tt*100;
                dw_read(set_reverse_t_tt_100,0x2100);
                reverse_t_display=0;
        }
        
                if(forward_volt_display==1)
        {                                                    //设置电压
                set_forward_volt_100=set_forward_volt*100;
                dw_read(set_forward_volt_100,0x2200);
                forward_volt_display=0;
        }
                else if(reverse_volt_display==1)
        {                                                    //设置电压
                set_reverse_volt_100=set_reverse_volt*100;
                dw_read(set_reverse_volt_100,0x2200);
                reverse_volt_display=0;
        }
        
        if(forward_display==1) dw_read(0x05,0x2300),forward_display=0;      //设置正反转
        else if(reverse_display==1) dw_read(0x06,0x2300),reverse_display=0;
        
}

if(mode==2)
{
        display_set(6);
        
        dw_read(0x00,0x1800);
        dw_read(0,0x1900);
        
        if(run_forward_flag==1)                        //正转运行
        {
                set_forward_t_100=set_forward_t*100;
                 dw_read(set_forward_t_100,0x2500);
               
               
                set_forward_volt_100=set_forward_volt*100;
                dw_read(set_forward_volt_100,0x2600);
               
                dw_read(0x05,0x2700);
        }
        else if(run_reverse_flag==1)                        //反转运行
        {
                set_reverse_t_100=set_reverse_t*100;
                 dw_read(set_reverse_t_100,0x2500);
               
               
                set_reverse_volt_100=set_reverse_volt*100;
                dw_read(set_reverse_volt_100,0x2600);
               
                dw_read(0x06,0x2700);
        }
               else dw_read(0,0x2500);
}

        
        
        memset(uart_buf,0,uart_index);
        uart_index=0;
}
uart.h:


#ifndef _UART__H
#define _UART__H
#include <AI8051U.H>
#include "stdio.h"
void Uart2_Init();
void uart_proc();
void dw_read(unsigned int dat,unsigned int addr);
void uart2_sendstr(unsigned char *puts,unsigned char len);
extern bit B_TX2_Busy;
extern unsigned int pwm_duty_100;
extern unsigned int set_volt_100;
#endif

wave1.c:

#include <AI8051U.H>
#include "wave1.h"
void Delay20us()        //@24.000MHz
{
        unsigned long edata i;
        _nop_();
        _nop_();
        _nop_();
        i = 118UL;
        while (i) i--;
}
void T0_init()    //定时器初始化
{
        TMOD &= 0xF0;                        //设置定时器模式
        TMOD |= 0x01;                        //设置定时器模式
        TL0 = 0;                                //设置定时初始值
        TH0 = 0;                                //设置定时初始值
        ET0=1;
}
void UT_init()    //超声波模块初始化
{
        echo=0;
        trig=0;
        T0_init();
}

void UT_trigger() //超声波触发函数
{
        trig=1;
        Delay20us();
        trig=0;
}

float dis_measure()
{
        float distance1;
        
        UT_trigger();
        P10=1;
        EA=0;
        while(echo==0);
        P10=0;
        EA=1;
        TR0=1;
        while((echo==1)&&(TF0==0));
        TR0=0;
        if(TF0==0)
        {
                distance1=((TH0*256.0+TL0)*0.0085)-0.4;               
                if(distance1<5||distance1>35) distance1=0;
                if(distance1>21) distance1=distance1+0.1;
                TH0=TL0=0;
                return distance1;        
        }
        else
        {
                TF0=0;
                return 0;
        }        
}

wave1.h:
#include <AI8051U.H>
sbit trig=P0^6;    //准双向
sbit echo=P0^7;    //高阻
void T0_init();
void UT_init();
void UT_trigger();
float dis_measure();
void Delay20us();


回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-3-24 06:02 , Processed in 0.464644 second(s), 84 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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