找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 253|回复: 5
打印 上一主题 下一主题
收起左侧

STC8G1K08+RX8025T+OLED万年历编译出错请教

[复制链接]
跳转到指定楼层
楼主
各位坛友老师好,以下是STC8G1K08+RX8025T+OLED万年历程序,编译不通过,我是新手。那位老师帮忙指点一下,在这里表示感谢!


编译错误截图


  1. #include <STC8G.H>
  2. #include <intrins.h>

  3. // 定义I2C引脚
  4. sbit SDA = P3^2;
  5. sbit SCL = P3^1;

  6. // 定义按键引脚
  7. sbit KEY_SET = P3^3;
  8. sbit KEY_UP = P3^4;
  9. sbit KEY_DN = P3^5;

  10. // OLED参数
  11. #define OLED_ADDR 0x3C    // OLED I2C地址
  12. #define RX8025T_ADDR 0x32 // RX8025T I2C地址

  13. // 星期定义
  14. char *weekdays[] = {"日", "一", "二", "三", "四", "五", "六"};

  15. // 时间结构体
  16. struct DateTime {
  17.     unsigned char second;
  18.     unsigned char minute;
  19.     unsigned char hour;
  20.     unsigned char day;    // 星期
  21.     unsigned char date;   // 日
  22.     unsigned char month;
  23.     unsigned char year;
  24. };

  25. // 全局变量
  26. struct DateTime currentTime;
  27. bit setMode = 0;         // 0:正常模式, 1:设置模式
  28. unsigned char setPos = 0; // 设置位置:0=年,1=月,2=日,3=时,4=分,5=秒
  29. unsigned char blinkCnt = 0; // 闪烁计数器

  30. // 函数声明
  31. void I2C_Start();
  32. void I2C_Stop();
  33. bit I2C_Write(unsigned char dat);
  34. unsigned char I2C_Read(bit ack);
  35. void OLED_WriteCmd(unsigned char cmd);
  36. void OLED_WriteData(unsigned char dat);
  37. void OLED_Init();
  38. void OLED_SetPos(unsigned char x, unsigned char y);
  39. void OLED_ShowChar(unsigned char x, unsigned char y, char c);
  40. void OLED_ShowStr(unsigned char x, unsigned char y, char *str);
  41. void RX8025T_ReadTime();
  42. void RX8025T_WriteTime();
  43. void Key_Scan();
  44. void Display_Time();
  45. void Display_Date();
  46. void Display_Temperature();
  47. void NumToStr(unsigned char num, char *str);
  48. void DelayMS(unsigned int ms);

  49. // I2C起始信号
  50. void I2C_Start() {
  51.     SDA = 1;
  52.     SCL = 1;
  53.     _nop_(); _nop_();
  54.     SDA = 0;
  55.     _nop_(); _nop_();
  56.     SCL = 0;
  57. }

  58. // I2C停止信号
  59. void I2C_Stop() {
  60.     SDA = 0;
  61.     SCL = 1;
  62.     _nop_(); _nop_();
  63.     SDA = 1;
  64.     _nop_(); _nop_();
  65. }

  66. // I2C写一个字节
  67. bit I2C_Write(unsigned char dat) {
  68.     unsigned char i;
  69.     bit ack;
  70.     for(i=0; i<8; i++) {
  71.         SDA = (dat & 0x80) ? 1 : 0;
  72.         dat <<= 1;
  73.         SCL = 1;
  74.         _nop_(); _nop_(); _nop_();
  75.         SCL = 0;
  76.     }
  77.     SDA = 1; // 释放SDA
  78.     SCL = 1;
  79.     _nop_(); _nop_();
  80.     ack = SDA; // 读取ACK
  81.     SCL = 0;
  82.     return ack;
  83. }

  84. // I2C读一个字节
  85. unsigned char I2C_Read(bit ack) {
  86.     unsigned char i, dat = 0;
  87.     SDA = 1; // 释放SDA
  88.     for(i=0; i<8; i++) {
  89.         SCL = 1;
  90.         _nop_(); _nop_();
  91.         dat <<= 1;
  92.         if(SDA) dat |= 0x01;
  93.         SCL = 0;
  94.         _nop_(); _nop_();
  95.     }
  96.     // 发送ACK/NACK
  97.     SDA = ack;
  98.     SCL = 1;
  99.     _nop_(); _nop_(); _nop_();
  100.     SCL = 0;
  101.     SDA = 1; // 释放SDA
  102.     return dat;
  103. }

  104. // OLED写命令
  105. void OLED_WriteCmd(unsigned char cmd) {
  106.     I2C_Start();
  107.     I2C_Write(OLED_ADDR << 1);
  108.     I2C_Write(0x00); // 命令标识
  109.     I2C_Write(cmd);
  110.     I2C_Stop();
  111. }

  112. // OLED写数据
  113. void OLED_WriteData(unsigned char dat) {
  114.     I2C_Start();
  115.     I2C_Write(OLED_ADDR << 1);
  116.     I2C_Write(0x40); // 数据标识
  117.     I2C_Write(dat);
  118.     I2C_Stop();
  119. }

  120. // OLED初始化
  121. void OLED_Init() {
  122.     DelayMS(100);
  123.     OLED_WriteCmd(0xAE); // 关闭显示
  124.    
  125.     OLED_WriteCmd(0xD5); // 设置显示时钟分频
  126.     OLED_WriteCmd(0x80);
  127.    
  128.     OLED_WriteCmd(0xA8); // 设置复用率
  129.     OLED_WriteCmd(0x3F);
  130.    
  131.     OLED_WriteCmd(0xD3); // 设置显示偏移
  132.     OLED_WriteCmd(0x00);
  133.    
  134.     OLED_WriteCmd(0x40); // 设置起始行
  135.    
  136.     OLED_WriteCmd(0x8D); // 电荷泵设置
  137.     OLED_WriteCmd(0x14); // 开启电荷泵
  138.    
  139.     OLED_WriteCmd(0x20); // 内存模式
  140.     OLED_WriteCmd(0x00); // 水平寻址模式
  141.    
  142.     OLED_WriteCmd(0xA1); // 段重映射
  143.     OLED_WriteCmd(0xC8); // 行重映射
  144.    
  145.     OLED_WriteCmd(0xDA); // 设置COM硬件
  146.     OLED_WriteCmd(0x12);
  147.    
  148.     OLED_WriteCmd(0x81); // 对比度设置
  149.     OLED_WriteCmd(0xCF);
  150.    
  151.     OLED_WriteCmd(0xD9); // 预充电周期
  152.     OLED_WriteCmd(0xF1);
  153.    
  154.     OLED_WriteCmd(0xDB); // VCOMH设置
  155.     OLED_WriteCmd(0x40);
  156.    
  157.     OLED_WriteCmd(0xA4); // 正常显示
  158.     OLED_WriteCmd(0xA6); // 非反转显示
  159.    
  160.     OLED_WriteCmd(0xAF); // 开启显示
  161. }

  162. // 设置显示位置
  163. void OLED_SetPos(unsigned char x, unsigned char y) {
  164.     OLED_WriteCmd(0xB0 + y); // 设置页地址
  165.     OLED_WriteCmd(((x & 0xF0) >> 4) | 0x10); // 设置列地址高4位
  166.     OLED_WriteCmd(x & 0x0F); // 设置列地址低4位
  167. }

  168. // 5x7字体字模
  169. const unsigned char Font5x7[][5] = {
  170.     {0x3E,0x45,0x49,0x51,0x3E}, // 0
  171.     {0x00,0x21,0x7F,0x01,0x00}, // 1
  172.     {0x23,0x45,0x49,0x49,0x31}, // 2
  173.     {0x22,0x49,0x49,0x49,0x36}, // 3
  174.     {0x0C,0x14,0x24,0x7F,0x04}, // 4
  175.     {0x72,0x51,0x51,0x51,0x4E}, // 5
  176.     {0x1E,0x29,0x49,0x49,0x06}, // 6
  177.     {0x40,0x47,0x48,0x50,0x60}, // 7
  178.     {0x36,0x49,0x49,0x49,0x36}, // 8
  179.     {0x30,0x49,0x49,0x4A,0x3C}, // 9
  180.     {0x00,0x36,0x36,0x00,0x00}, // :
  181.     {0x00,0x00,0x7F,0x00,0x00}, // -
  182.     {0x7F,0x48,0x48,0x48,0x30}, // T
  183.     {0x41,0x22,0x1C,0x22,0x41}  // W
  184. };

  185. // 显示单个字符
  186. void OLED_ShowChar(unsigned char x, unsigned char y, char c,unsigned char i) {
  187.     unsigned char idx = 0;
  188.    
  189.     if(c >= '0' && c <= '9') {
  190.         idx = c - '0';
  191.     }
  192.     else if(c == ':') {
  193.         idx = 10;
  194.     }
  195.     else if(c == '-') {
  196.         idx = 11;
  197.     }
  198.     else if(c == 'T') {
  199.         idx = 12;
  200.     }
  201.     else if(c == 'W') {
  202.         idx = 13;
  203.     }
  204.     else {
  205.         return; // 不支持的字符
  206.     }
  207.    
  208.     OLED_SetPos(x, y);
  209.    // for(unsigned char i=0; i<5; i++) {
  210.                          for(i=0; i<5; i++) {
  211.         OLED_WriteData(Font5x7[idx][i]);
  212.     }
  213.     OLED_WriteData(0x00); // 字符间距
  214. }

  215. // 显示字符串
  216. void OLED_ShowStr(unsigned char x, unsigned char y, char *str) {
  217.     while(*str) {
  218.         OLED_ShowChar(x, y, *str++);
  219.         x += 6; // 每个字符占6列(5像素+1间距)
  220.     }
  221. }

  222. // 数字转字符串
  223. void NumToStr(unsigned char num, char *str) {
  224.     str[0] = num / 10 + '0';
  225.     str[1] = num % 10 + '0';
  226.     str[2] = '\0';
  227. }

  228. // 从RX8025T读取时间
  229. void RX8025T_ReadTime() {
  230.     I2C_Start();
  231.     I2C_Write(RX8025T_ADDR << 1); // 写地址
  232.     I2C_Write(0x00); // 起始地址(秒寄存器)
  233.    
  234.     I2C_Start();
  235.     I2C_Write((RX8025T_ADDR << 1) | 0x01); // 读地址
  236.    
  237.     currentTime.second = I2C_Read(1); // 发送ACK继续读
  238.     currentTime.minute = I2C_Read(1);
  239.     currentTime.hour   = I2C_Read(1);
  240.     currentTime.day    = I2C_Read(1);
  241.     currentTime.date   = I2C_Read(1);
  242.     currentTime.month  = I2C_Read(1);
  243.     currentTime.year   = I2C_Read(0); // 最后字节发送NACK
  244.     I2C_Stop();
  245.    
  246.     // 转换BCD码
  247.     currentTime.second = (currentTime.second >> 4) * 10 + (currentTime.second & 0x0F);
  248.     currentTime.minute = (currentTime.minute >> 4) * 10 + (currentTime.minute & 0x0F);
  249.     currentTime.hour   = (currentTime.hour >> 4) * 10 + (currentTime.hour & 0x0F);
  250.     currentTime.date   = (currentTime.date >> 4) * 10 + (currentTime.date & 0x0F);
  251.     currentTime.month  = (currentTime.month >> 4) * 10 + (currentTime.month & 0x0F);
  252.     currentTime.year   = (currentTime.year >> 4) * 10 + (currentTime.year & 0x0F);

  253. }

  254. // 向RX8025T写入时间
  255. void RX8025T_WriteTime() {
  256.     I2C_Start();
  257.     I2C_Write(RX8025T_ADDR << 1); // 写地址
  258.     I2C_Write(0x00); // 起始地址(秒寄存器)
  259.    
  260.     // 转换BCD码
  261.     I2C_Write(((currentTime.second / 10) << 4) | (currentTime.second % 10));
  262.     I2C_Write(((currentTime.minute / 10) << 4) | (currentTime.minute % 10));
  263.     I2C_Write(((currentTime.hour / 10) << 4) | (currentTime.hour % 10));
  264.     I2C_Write(currentTime.day);
  265.     I2C_Write(((currentTime.date / 10) << 4) | (currentTime.date % 10));
  266.     I2C_Write(((currentTime.month / 10) << 4) | (currentTime.month % 10));
  267.     I2C_Write(((currentTime.year / 10) << 4) | (currentTime.year % 10));
  268.    
  269.     I2C_Stop();
  270. }

  271. // 按键扫描
  272. void Key_Scan() {
  273.     static unsigned char keyCount = 0;
  274.     static bit keyFlag = 0;
  275.    
  276.     if(!KEY_SET || !KEY_UP || !KEY_DN) {
  277.         keyCount++;
  278.         if(keyCount >= 20) { // 消抖
  279.             keyCount = 0;
  280.             if(!keyFlag) {
  281.                 keyFlag = 1;
  282.                
  283.                 if(!KEY_SET) {
  284.                     if(!setMode) {
  285.                         setMode = 1;
  286.                         setPos = 0; // 进入设置模式
  287.                     }
  288.                     else {
  289.                         setPos++; // 切换到下一个设置项
  290.                         if(setPos > 5) { // 设置完成
  291.                             setMode = 0;
  292.                             RX8025T_WriteTime(); // 保存时间
  293.                         }
  294.                     }
  295.                 }
  296.                
  297.                 if(setMode) {
  298.                     if(!KEY_UP) {
  299.                         switch(setPos) {
  300.                             case 0: currentTime.year = (currentTime.year < 99) ? currentTime.year+1 : 0; break;
  301.                             case 1: currentTime.month = (currentTime.month < 12) ? currentTime.month+1 : 1; break;
  302.                             case 2: currentTime.date = (currentTime.date < 31) ? currentTime.date+1 : 1; break;
  303.                             case 3: currentTime.hour = (currentTime.hour < 23) ? currentTime.hour+1 : 0; break;
  304.                             case 4: currentTime.minute = (currentTime.minute < 59) ? currentTime.minute+1 : 0; break;
  305.                             case 5: currentTime.second = (currentTime.second < 59) ? currentTime.second+1 : 0; break;
  306.                         }
  307.                     }
  308.                     
  309.                     if(!KEY_DN) {
  310.                         switch(setPos) {
  311.                             case 0: currentTime.year = (currentTime.year > 0) ? currentTime.year-1 : 99; break;
  312.                             case 1: currentTime.month = (currentTime.month > 1) ? currentTime.month-1 : 12; break;
  313.                             case 2: currentTime.date = (currentTime.date > 1) ? currentTime.date-1 : 31; break;
  314.                             case 3: currentTime.hour = (currentTime.hour > 0) ? currentTime.hour-1 : 23; break;
  315.                             case 4: currentTime.minute = (currentTime.minute > 0) ? currentTime.minute-1 : 59; break;
  316.                             case 5: currentTime.second = (currentTime.second > 0) ? currentTime.second-1 : 59; break;
  317.                         }
  318.                     }
  319.                 }
  320.             }
  321.         }
  322.     }
  323.     else {
  324.         keyCount = 0;
  325.         keyFlag = 0;
  326.     }
  327. }

  328. // 显示日期
  329. void Display_Date() {
  330.     char str[3];
  331.    
  332.     // 显示年月日
  333.     OLED_ShowStr(0, 0, "20");
  334.     NumToStr(currentTime.year, str);
  335.     OLED_ShowStr(12, 0, str);
  336.     OLED_ShowChar(24, 0, '-');
  337.    
  338.     NumToStr(currentTime.month, str);
  339.     OLED_ShowStr(30, 0, str);
  340.     OLED_ShowChar(42, 0, '-');
  341.    
  342.     NumToStr(currentTime.date, str);
  343.     OLED_ShowStr(48, 0, str);
  344.    
  345.     // 显示星期
  346.     OLED_ShowStr(72, 0, "W");
  347.     str[0] = '0' + (currentTime.day % 7); // 显示0-6
  348.     str[1] = '\0';
  349.     OLED_ShowStr(78, 0, str);
  350. }

  351. // 显示时间
  352. void Display_Time() {
  353.     char str[3];
  354.    
  355.     NumToStr(currentTime.hour, str);
  356.     OLED_ShowStr(0, 2, str);
  357.     OLED_ShowChar(12, 2, ':');
  358.    
  359.     NumToStr(currentTime.minute, str);
  360.     OLED_ShowStr(18, 2, str);
  361.     OLED_ShowChar(30, 2, ':');
  362.    
  363.     NumToStr(currentTime.second, str);
  364.     OLED_ShowStr(36, 2, str);
  365. }
  366. }

  367. // 主函数
  368. void main() {
  369.     // 初始化IO口
  370.     P3M0 = 0x00;
  371.     P3M1 = 0x00; // 准双向模式
  372.    
  373.     // 初始化OLED
  374.     OLED_Init();
  375.    
  376.     // 初始化时间 (示例时间)
  377.     currentTime.year = 23;
  378.     currentTime.month = 1;
  379.     currentTime.date = 1;
  380.     currentTime.day = 0; // 星期日
  381.     currentTime.hour = 12;
  382.     currentTime.minute = 0;
  383.     currentTime.second = 0;
  384.     RX8025T_WriteTime(); // 写入初始时间
  385.    
  386.     while(1) {
  387.         RX8025T_ReadTime(); // 读取时间
  388.         Key_Scan();         // 按键扫描
  389.         
  390.         // 清屏
  391.         OLED_WriteCmd(0x20); // 水平寻址模式
  392.         OLED_WriteCmd(0x00); // 列起始地址0
  393.         OLED_WriteCmd(0x10); // 列结束地址127
  394.         OLED_WriteCmd(0x00); // 页起始地址0
  395.         OLED_WriteCmd(0x07); // 页结束地址7
  396.         
  397.         // 显示信息
  398.         Display_Date();
  399.         Display_Time();
  400.         Display_Temperature();
  401.         
  402.         // 设置模式闪烁指示
  403.         if(setMode) {
  404.             blinkCnt++;
  405.             if(blinkCnt > 100) {
  406.                 switch(setPos) {
  407.                     case 0: OLED_ShowStr(12, 0, "  "); break; // 年
  408.                     case 1: OLED_ShowStr(30, 0, "  "); break; // 月
  409.                     case 2: OLED_ShowStr(48, 0, "  "); break; // 日
  410.                     case 3: OLED_ShowStr(0, 2, "  "); break;  // 时
  411.                     case 4: OLED_ShowStr(18, 2, "  "); break; // 分
  412.                     case 5: OLED_ShowStr(36, 2, "  "); break; // 秒
  413.                 }
  414.                 if(blinkCnt > 200) blinkCnt = 0;
  415.             }
  416.         }
  417.         
  418.         DelayMS(10);
  419.     }
  420. }

  421. // 简单延时函数
  422. void DelayMS(unsigned int ms) {
  423.     unsigned int i, j;
  424.     for(i=0; i<ms; i++)
  425.         for(j=0; j<1000; j++);
  426. }
复制代码




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:584814 发表于 2025-6-9 15:24 | 只看该作者
在 OLED_ShowChar()函数中,一会儿带3个参数一会儿带4个参数整 EMO 了
回复

使用道具 举报

板凳
ID:437129 发表于 2025-6-9 15:38 | 只看该作者
man1234567 发表于 2025-6-9 15:24
在 OLED_ShowChar()函数中,一会儿带3个参数一会儿带4个参数整 EMO 了

老师好,源程序是从网上找的,最开始带3个参数,第4个参数是写在下面的,编译后显示共有7个错误。将错误信息复制到百度查询后提示变量声明要放在前面,所以提到前面去了,现在显示只有一个错误了。
我是初学者,还没入门,请老师多多指教,谢谢!
回复

使用道具 举报

地板
ID:1121801 发表于 2025-6-9 16:22 | 只看该作者
OLED_ShowChar函数定义长度不一致,定义函数时是三个参数,写函数时是四个参数.
回复

使用道具 举报

5#
ID:437129 发表于 2025-6-9 20:10 | 只看该作者
cyi8 发表于 2025-6-9 16:22
OLED_ShowChar函数定义长度不一致,定义函数时是三个参数,写函数时是四个参数.

受教了,我试试看。谢谢!
回复

使用道具 举报

6#
ID:401564 发表于 2025-6-15 17:53 | 只看该作者
虽然写单片机程序,到最后,大多不是复制自己的代码,就是复制别人的代码
但我觉得,刚入门的时候,最好还是自己去看一下器件的规格书,代码最好是自己一个一个打上去的,这样的话,基础会好一些,后期学习的进度也会快很多
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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