找回密码
 立即注册
查看: 34|回复: 1

大四毕业设计,AI8051U单片机轻松帮我搞定毕设

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2026-04-18 23:43:01
已绑定手机

6

主题

14

回帖

66

积分

注册会员

积分
66
发表于 2026-4-18 23:43:01 | 显示全部楼层 |阅读模式
转眼间大学生活已接近尾声,毕业设计成为我大学期间最后一次综合性实践。从最初确定课题、梳理方案,到一步步完成硬件搭建、程序编写、系统调试,整个过程充满挑战与成长。而在这段关键历程中,STC AI8051U 擎天柱核心功能板单片机凭借稳定可靠的性能、简洁易用的开发体验,以及丰富的学习资源,成为我顺利完成毕设的关键助力。
我的毕业设计题目是基于 AI8051U 单片机的宠物自动投料喂食器控制系统,主要实现定时定量喂食、手动应急投料、重量检测、OLED 状态显示等功能。系统涉及单片机控制、PWM 舵机驱动、HX711 称重采集、矩阵键盘输入、时钟模块等多个部分,对芯片的 IO 资源、定时器、稳定性都有一定要求。在芯片选型阶段,我曾担心普通单片机资源不足、驱动复杂、调试困难,而在老师的建议下,我选择了 STC AI8051U 擎天柱,事实证明,这一选择让我的整个设计过程事半功倍。
AI8051U 最打动我的一点是上手快、兼容性强、学习成本低。它基于经典增强型 8051 内核,与课堂所学知识高度契合,不需要重新学习复杂架构,让我能快速进入开发状态。同时,官方提供的例程、工具和文档非常完善,再加上论坛里大量实用教程和经验分享,让我在面对舵机驱动、称重采集、键盘消抖等难点时,总能找到清晰思路,少走了大量弯路。
在程序开发阶段,AI8051U 的优势更加明显。芯片拥有充足的 GPIO 口,可轻松连接键盘、OLED、舵机、称重传感器等模块,引脚分配灵活,布线简洁。多路定时器和 PWM 功能让 SG90 舵机控制更加精准,投料角度稳定,不会出现抖动、漏投或多投现象。在编写 HX711 称重程序时,AI8051U 的 IO 口响应速度快、时序稳定,数据采集准确,配合简单滤波即可实现可靠的定量检测。同时,芯片支持 USB 直接下载程序,调试方便快捷,大幅提高开发效率。
系统联调过程中,我遇到过定时不准、按键抖动、舵机干扰等问题,但 AI8051U 凭借稳定的中断系统、良好的抗干扰能力和灵活的配置方式,让这些问题都能快速解决。无论是时钟模块的掉电记忆功能,还是 OLED 屏幕的实时刷新显示,亦或是多模块协同工作,AI8051U 都表现得稳定可靠,确保整个喂食系统运行流畅。
回顾整个毕业设计过程,从方案设计到最终实现,STC AI8051U 擎天柱始终是我最可靠的伙伴。它性能够用、资料齐全、稳定性强、成本友好,特别适合本科生做毕业设计使用。它不仅帮我完成了课题要求,更让我在实践中巩固了嵌入式系统、单片机原理、硬件调试等专业知识,提升了工程实践能力。
在此,我衷心感谢指导老师的耐心帮助,也感谢 STC 提供如此优秀的单片机产品与学习生态。如果你也正在做单片机类毕业设计,纠结主控芯片,我真心推荐STC AI8051U 擎天柱,它简单、强大、靠谱,能帮你高效、顺利地完成毕业设计,轻松迈过大学最后一道关卡。
  1. #ifndef __CONFIG_H__
  2. #define __CONFIG_H__
  3. #include "ai8051u.h"
  4. #define MAIN_Fosc 40000000UL
  5. // ==================== 引脚定义 ====================
  6. sbit OLED_SCL = P2^4;
  7. sbit OLED_SDA = P2^3;
  8. #define OLED_ADDR    0x78
  9. sbit HX711_DOUT = P1^0;
  10. sbit HX711_SCK = P1^1;
  11. sbit SG90 = P1^4;
  12. sbit WATER_PUMP = P1^5;
  13. sbit KEY_MODE = P3^2;      // 自动/手动切换 / 增加值
  14. sbit KEY_SET = P3^3;       // 时间设置(短按)
  15. sbit KEY_SYS_SET = P4^7;   // 系统设置进入按键(短按P4.7)
  16. // ==================== 称重参数 ====================
  17. #define HX711_GapValue       453.1f
  18. #define HX711_SAMPLE_TIMES   3
  19. #define HX711_MAOPI_TIMES    10
  20. // ==================== 舵机参数 ====================
  21. #define SERVO_PWM_0      16
  22. #define SERVO_PWM_180    64
  23. // ==================== 系统参数 ====================
  24. extern unsigned int Weight_Threshold;      // 重量阈值(g)
  25. // ==================== 水位参数 ====================
  26. #define WATER_DRY_ADC           4
  27. #define WATER_WET_ADC           46500
  28. #define WATER_LOW_THRESHOLD     10
  29. #define WATER_HIGH_THRESHOLD    90
  30. // ==================== 时间设置参数 ====================
  31. #define TIME_SET_MODE_NONE      0
  32. #define TIME_SET_MODE_YEAR      1
  33. #define TIME_SET_MODE_MONTH     2
  34. #define TIME_SET_MODE_DAY       3
  35. #define TIME_SET_MODE_HOUR      4
  36. #define TIME_SET_MODE_MINUTE    5
  37. #define TIME_SET_MODE_SECOND    6
  38. // ==================== 状态机定义 ====================
  39. #define STATE_IDLE      0
  40. #define STATE_FEEDING   1
  41. #define STATE_WAITING   2
  42. #define STATE_RETURN    3
  43. // ==================== 系统设置模式定义 ====================
  44. #define SYS_SET_MODE_NONE       0
  45. #define SYS_SET_MODE_TIME1      1   // 设置投喂时间1
  46. #define SYS_SET_MODE_TIME2      2   // 设置投喂时间2
  47. #define SYS_SET_MODE_TIME3      3   // 设置投喂时间3
  48. #define SYS_SET_MODE_WEIGHT     4   // 设置重量阈值
  49. #define SYS_SET_MODE_EXIT       5
  50. // ==================== 时间设置子模式(用于时分切换)====================
  51. #define TIME_SUB_MODE_HOUR      0
  52. #define TIME_SUB_MODE_MINUTE    1
  53. // ==================== 全局变量声明 ====================
  54. extern float Weight_Maopi;
  55. extern float Weight_Shiwu;
  56. extern unsigned int Weight;
  57. extern unsigned int Weight_g;
  58. extern unsigned int year;
  59. extern unsigned char month;
  60. extern unsigned char day;
  61. extern unsigned char hour;
  62. extern unsigned char minute;
  63. extern unsigned char second;
  64. extern unsigned char Servo_State;
  65. extern unsigned char Servo_Angle;
  66. extern unsigned int Servo_Pulse_Count;
  67. extern volatile unsigned int System_Time;
  68. extern unsigned int Cycle_Timer;
  69. extern unsigned int Motion_Timer;
  70. extern bit Auto_Mode;
  71. extern unsigned int Manual_Delay;
  72. extern bit Manual_Trigger;
  73. extern bit Key_Pressed;
  74. extern unsigned int Water_ADC_Raw;
  75. extern unsigned char Water_Percent;
  76. extern unsigned char Water_Status;
  77. extern unsigned char Time_Set_Mode;
  78. extern unsigned char Set_Flash_Cnt;
  79. extern bit Time_Set_Active;
  80. // 系统参数设置相关变量
  81. extern unsigned int Sys_Weight_Threshold;
  82. extern unsigned char Sys_Set_Mode;
  83. extern bit Sys_Set_Active;
  84. extern unsigned char Sys_Feed_Hour[3];     // 存储三个投喂时间的小时(0-23)
  85. extern unsigned char Sys_Feed_Minute[3];   // 存储三个投喂时间的分钟(0-59)
  86. extern unsigned char Time_Sub_Mode;        // 当前调整小时还是分钟(仅系统设置界面有效)
  87. // 投喂时间点(小时和分钟可调)
  88. extern unsigned char feed_hour[3];
  89. extern unsigned char feed_minute[3];
  90. extern unsigned char feed_flag[3];         // 当天是否已投喂标志
  91. #endif
  92. * 文件名:adc.c
  93. * 描述:ADC和水位传感器驱动(带突变保持功能)
  94. *********************************************************************/
  95. #include "../System/config.h"
  96. #include "../System/delay.h"
  97. #include "adc.h"
  98. extern unsigned int Water_ADC_Raw;
  99. extern unsigned char Water_Percent;
  100. extern unsigned char Water_Status;
  101. // 静态变量:用于滤波和突变保持
  102. static unsigned int filter_buffer[5] = {0};    // 滑动滤波缓冲区
  103. static unsigned char filter_index = 0;
  104. static unsigned int last_stable_adc = 0;       // 上一次稳定ADC值
  105. static unsigned char last_stable_percent = 0;   // 上一次稳定百分比
  106. static unsigned char jump_counter = 0;          // 突变计数器
  107. // ==================== 滑动平均滤波 ====================
  108. static unsigned int SlidingFilter(unsigned int new_value)
  109. {
  110.     unsigned char i;
  111.     unsigned long sum = 0;
  112.    
  113.     filter_buffer[filter_index] = new_value;
  114.     filter_index++;
  115.     if(filter_index >= 5) filter_index = 0;
  116.    
  117.     for(i = 0; i < 5; i++)
  118.     {
  119.         sum += filter_buffer[i];
  120.     }
  121.    
  122.     return (unsigned int)(sum / 5);
  123. }
  124. // ==================== 水位百分比计算 ====================
  125. static unsigned char GetWaterPercent(unsigned int adc_raw)
  126. {
  127.     if(adc_raw <= WATER_DRY_ADC)
  128.         return 0;
  129.     else if(adc_raw >= WATER_WET_ADC)
  130.         return 100;
  131.     else
  132.         return (unsigned char)((unsigned long)(adc_raw - WATER_DRY_ADC) * 100 / (WATER_WET_ADC - WATER_DRY_ADC));
  133. }
  134. // ==================== ADC单次读取 ====================
  135. static unsigned int ADC_ReadValue(unsigned char channel)
  136. {
  137.     unsigned int adc_value;
  138.     unsigned int timeout = 10000;
  139.    
  140.     P_SW2 |= 0x80;
  141.    
  142.     ADC_CONTR = 0x80 | (channel & 0x0F) | 0x40;
  143.    
  144.     while(!(ADC_CONTR & 0x20) && --timeout);
  145.    
  146.     if(timeout == 0) {
  147.         P_SW2 &= ~0x80;
  148.         return last_stable_adc;
  149.     }
  150.    
  151.     ADC_CONTR &= ~0x20;
  152.    
  153.     adc_value = ADC_RES;
  154.     adc_value <<= 8;
  155.     adc_value |= ADC_RESL;
  156.    
  157.     P_SW2 &= ~0x80;
  158.    
  159.     return adc_value;
  160. }
  161. // ==================== ADC初始化 ====================
  162. void ADC_Init(void)
  163. {
  164.     unsigned char i;
  165.     unsigned int init_val;
  166.    
  167.     // 设置P1.6为高阻输入
  168.     P1M1 |= 0x40;
  169.     P1M0 &= ~0x40;
  170.    
  171.     // 开启扩展寄存器访问
  172.     P_SW2 |= 0x80;
  173.    
  174.     ADCCFG = 0x0F;
  175.     ADC_CONTR = 0x80;
  176.    
  177.     P_SW2 &= ~0x80;
  178.    
  179.     delay_ms(10);
  180.    
  181.     // 初始化滤波器
  182.     init_val = ADC_ReadValue(6);
  183.     for(i = 0; i < 5; i++)
  184.     {
  185.         filter_buffer[i] = init_val;
  186.     }
  187.     last_stable_adc = init_val;
  188.     last_stable_percent = GetWaterPercent(init_val);
  189. }
  190. // ==================== 水位传感器读取(突变保持版本)====================
  191. void WaterSensor_Read(void)
  192. {
  193.     unsigned int raw_adc;
  194.     unsigned int filtered_adc;
  195.     unsigned char new_percent;
  196.     unsigned char percent_change;
  197.     static unsigned char last_percent = 0;
  198.    
  199.     // ========== 第1步:读取原始ADC值 ==========
  200.     raw_adc = ADC_ReadValue(6);
  201.    
  202.     // ========== 第2步:滑动平均滤波 ==========
  203.     filtered_adc = SlidingFilter(raw_adc);
  204.    
  205.     // ========== 第3步:计算当前水位百分比 ==========
  206.     new_percent = GetWaterPercent(filtered_adc);
  207.    
  208.     // ========== 第4步:计算变化量 ==========
  209.     if(new_percent > last_percent)
  210.         percent_change = new_percent - last_percent;
  211.     else
  212.         percent_change = last_percent - new_percent;
  213.    
  214.     // ========== 第5步:突变检测与保持 ==========
  215.     // 如果变化超过30%(触摸干扰),认为是突变
  216.     if(percent_change > 30)
  217.     {
  218.         jump_counter++;
  219.         // 连续3次突变才认为是真实变化,否则保持上次值
  220.         if(jump_counter < 3)
  221.         {
  222.             // 保持上次值,忽略突变
  223.             new_percent = last_percent;
  224.             filtered_adc = last_stable_adc;
  225.         }
  226.         else
  227.         {
  228.             // 连续3次突变,认为是真实变化
  229.             jump_counter = 0;
  230.             last_stable_adc = filtered_adc;
  231.             last_stable_percent = new_percent;
  232.         }
  233.     }
  234.     else
  235.     {
  236.         // 正常变化,清零突变计数器
  237.         jump_counter = 0;
  238.         last_stable_adc = filtered_adc;
  239.         last_stable_percent = new_percent;
  240.     }
  241.    
  242.     // ========== 第6步:保存最终值 ==========
  243.     Water_ADC_Raw = last_stable_adc;
  244.     Water_Percent = last_stable_percent;
  245.     last_percent = Water_Percent;
  246.    
  247.     // ========== 第7步:状态判断 ==========
  248.     if(Water_Percent <= WATER_LOW_THRESHOLD)
  249.         Water_Status = 0;   // 缺水
  250.     else if(Water_Percent >= WATER_HIGH_THRESHOLD)
  251.         Water_Status = 2;   // 充足
  252.     else
  253.         Water_Status = 1;   // 正常
  254. } * 文件名:hx711.c
  255. * 描述:HX711称重传感器驱动
  256. *********************************************************************/
  257. #include "../System/config.h"
  258. #include "../System/delay.h"
  259. #include "hx711.h"
  260. extern float Weight_Maopi;
  261. extern float Weight_Shiwu;
  262. // 微秒级延时,给HX711通信提供时序
  263. static void HX711_DelayUs(void)
  264. {
  265.     _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
  266. }
  267. // 读取HX711的24位AD原始值(称重传感器核心数据)
  268. static unsigned long HX711_Read(void)
  269. {
  270.     unsigned long count = 0;
  271.     unsigned char i;
  272.    
  273.     HX711_DOUT = 1;
  274.     HX711_DelayUs();
  275.     HX711_SCK = 0;
  276.    
  277.     while(HX711_DOUT);  // 等待数据准备好
  278.    
  279.     // 读取24位数据
  280.     for(i = 0; i < 24; i++)
  281.     {
  282.         HX711_SCK = 1;
  283.         count <<= 1;
  284.         HX711_DelayUs();
  285.         HX711_SCK = 0;
  286.         if(HX711_DOUT) count++;
  287.         HX711_DelayUs();
  288.     }
  289.    
  290.     HX711_SCK = 1;
  291.     count ^= 0x800000;  // 符号位处理
  292.     HX711_DelayUs();
  293.     HX711_SCK = 0;
  294.    
  295.     return count;
  296. }
  297. // 多次采样取平均值,让重量更稳定
  298. static unsigned long HX711_ReadAverage(unsigned char times)
  299. {
  300.     unsigned long sum = 0;
  301.     unsigned char i;
  302.     for(i = 0; i < times; i++)
  303.     {
  304.         sum += HX711_Read();
  305.         delay_ms(1);
  306.     }
  307.     return sum / times;
  308. }
  309. // 去皮(获取空盘子的重量值)
  310. void Get_Maopi(void)
  311. {
  312.     Weight_Maopi = (float)HX711_ReadAverage(HX711_MAOPI_TIMES);
  313. }
  314. // 获取最终实际重量(克)
  315. unsigned int Get_Weight(void)
  316. {
  317.     unsigned long adc;
  318.     adc = HX711_ReadAverage(HX711_SAMPLE_TIMES);
  319.    
  320.     // 当前重量 - 去皮重量 = 实物重量
  321.     if(adc > Weight_Maopi)
  322.     {
  323.         Weight_Shiwu = (float)(adc - Weight_Maopi);
  324.         Weight_Shiwu = Weight_Shiwu / HX711_GapValue;  // 转为克
  325.         if(Weight_Shiwu < 0.2f) Weight_Shiwu = 0;      // 小重量清零
  326.     }
  327.     else
  328.     {
  329.         Weight_Shiwu = 0;
  330.     }
  331.    
  332.     return (unsigned int)(Weight_Shiwu * 100);  // 返回扩大100倍的重量值
  333. }
复制代码


屏幕截图 2026-04-18 233852.png
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2026-04-18 23:43:01
已绑定手机

6

主题

14

回帖

66

积分

注册会员

积分
66
发表于 2026-4-18 23:44:24 | 显示全部楼层
https://www.stcaimcu.com/forum.php?mod=attachment&aid=MTM2MDI3fDcxZDViMmYxfDE3Nzc2MDI2MTV8MHw%3D[img][/img]
截图202604182343595996.jpg
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-5-1 10:30 , Processed in 0.119188 second(s), 57 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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