完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
想做一个电子名牌,上位机端大致已经弄好,现在单片机端程序还有问题。程序首先读取eeprom的数据存储到显示数组中,初始化串口,根据标志位决定是否擦除扇区,并将通过串口接受的数据存入eeprom,实质就是看串口有无数据进来,没有就显示原本存储的数据,标志位是一个全局变量,由中断程序控制值。代码我贴在下面,目前就是使用isp打开串口后,显示会短暂显示一下,发送数据不起作用,有没有大神解答一下问题。
#include #include "eeprom.h" #define uchar unsigned char #define uint unsigned int /* 点阵显示宏定义 */ sbit KEY = P3 ^ 2; sbit T_STR = P3 ^ 7; // 锁存引脚 sbit T_IO = P1 ^ 4; // 数据引脚 sbit T_CLK = P3 ^ 6; // 时钟引脚 sbit T_OE = P3 ^ 5; uchar row = 0, col; uchar xdata receivedData[16][8]; uchar xdata buffer[256]; uchar flag = 0; uchar count = 0; uint eepromAddress = 0x0000; void Uartinit(void) { PCON &= 0x7F; // 波特率不倍速 SCON = 0x50; // 8位数据,可变波特率 AUXR |= 0x40; // 定时器1时钟为Fosc AUXR &= 0xFE; // 串口1选择定时器1为波特率发生器 TMOD &= 0x0F; // 清除定时器1模式位 TMOD |= 0x20; // 设定定时器1为8位自动重装方式 TL1 = 0xDC; // 设定初值 TH1 = 0xDC; // 设定定时器重装初值 ET1 = 0; // 禁止定时器1中断 TR1 = 1; // 启动定时器1 ES = 1; // 开启串口中断允许 EA = 1; // 开启全局中断允许 } unsigned char AsciiToHex(unsigned char ascii) { if (ascii >= '0' && ascii <= '9') { return ascii - '0'; // 将字符 '0'-'9' 转换为 0x0-0x9 } else if (ascii >= 'A' && ascii <= 'F') { return ascii - 'A' + 0xA; // 将字符 'A'-'F' 转换为 0xA-0xF } else { return 0x00; // 如果不在范围内,返回默认值 0x00 } } void ReadFromEeprom(uint address) { uint i, j; for (i = 0; i < 16; i++) { // 遍历16行 for (j = 0; j < 8; j++) { // 每行8个字节 unsigned char highByteAscii = IapReadByte(address); // 读取高位 ASCII unsigned char lowByteAscii = IapReadByte(address + 1); // 读取低位 ASCII // 转换 ASCII 值为十六进制数字 unsigned char highByte = AsciiToHex(highByteAscii); unsigned char lowByte = AsciiToHex(lowByteAscii); // 合并高、低位为一个8位的十六进制数 receivedData[i][j] = (highByte << 4) | (lowByte & 0x0F); address += 2; // 每次读取后地址增加2,以读取下一个字节对 } } } void WriteToEeprom(uint address, uchar data1) { IapProgramByte(address, data1); // 使用定义好的函数写入EEPROM } void Delay(unsigned int t) { while (--t); } void InputByte(unsigned char dat) { unsigned char i; for (i = 0; i < 8; i++) { T_IO = !(dat & 0x01); dat >>= 1; T_CLK = 0; T_CLK = 1; } } void SendString(uchar *str) { while (*str) { SBUF = *str++; while (!TI); TI = 0; } } void main(void) { uint i; ReadFromEeprom(eepromAddress); eepromAddress = 0x0000; UartInit(); SendString("2"); // 发送 "2" 表示初始化完成 P3M0 = 0xff; // 推挽 P1M0 = 0xff; P3M1 = 0; P1M1 = 0; AUXR |= 0x80; while(1) { if(flag == 1) { ES = 0; SendString("3"); // 当接收到完整数据包后发送 "3" IapEraseSector(0x0000); for(i = 0; i < 256; i++) { WriteToEeprom(eepromAddress++, buffer[i]); } eepromAddress = 0x0000; ReadFromEeprom(eepromAddress); eepromAddress = 0x0000; flag = 0; ES = 1; } Delay(1); T_OE = 0; T_STR = 0; // 锁存无效 for (col = 0; col < 8; col++) { InputByte(receivedData[row][col]); // 输出到 595 } P1 = row; // 用 P1 口的前 4 位控制 16 行 T_STR = 1; // 锁存有效,此时一行的数据显示到屏上 T_OE = 1; row++; if (row == 16) { row = 0; } } } void ser() interrupt 4 { uchar receivedByte = SBUF; buffer[count++] = receivedByte; //SendString("6"); if (count == 256) { flag = 1; count = 0; SendString("1"); RI = 0; // 清除接收标志位 } } |
|
相关推荐
1个回答
|
|
根据您提供的代码和描述,我会尝试分析可能的问题,并给出一些建议。首先,您的代码中有一些关键部分没有提供,例如点阵显示宏定义、串口初始化和中断服务程序等。因此,我将基于您提供的信息,给出一些可能的问题和解决方案。
1. 串口初始化问题: 确保您已经正确初始化了串口,包括波特率、工作模式等。您可以使用以下代码初始化串口: ```c void UartInit() { SCON = 0x50; // 模式1,8位数据,可变波特率 TMOD |= 0x20; // 定时器1,模式2 TH1 = 0xFD; // 设置波特率为9600 TL1 = 0xFD; TR1 = 1; // 启动定时器1 ES = 1; // 启用串口中断 EA = 1; // 启用全局中断 } ``` 2. 串口中断服务程序问题: 确保您的串口中断服务程序能够正确处理接收到的数据,并将其存储到EEPROM中。以下是一个示例: ```c void Uart_ISR() interrupt 4 { if (RI) { RI = 0; // 清除接收中断标志 uchar data = SBUF; // 读取接收到的数据 // 将数据存储到EEPROM中 WriteEEPROM(data); } } ``` 3. EEPROM写入问题: 确保您的EEPROM写入函数能够正确写入数据。以下是一个示例: ```c void WriteEEPROM(uchar data) { uchar addr = 0; // EEPROM地址 EA = 0; // 关闭全局中断 EEM0 = 0; // 选择EEPROM EEM1 = 1; EA = 1; // 开启全局中断 EERP0 = addr; // 设置EEPROM地址 EERP1 = addr >> 8; EEDAT = data; // 设置要写入的数据 EECON1 = 0x90; // 设置写入命令 _nop_(); // 等待一个机器周期 _nop_(); _nop_(); _nop_(); EECON1 = 0x80; // 启动写入操作 while (EECON1 & 0x01); // 等待写入完成 } ``` 4. 显示问题: 确保您的显示函数能够正确显示存储在数组中的数据。以下是一个示例: ```c void Display() { uchar i; for (i = 0; i < 8; i++) { // 根据您的点阵显示宏定义,设置相应的引脚 P1 = displayArray[i]; // 将数据发送到点阵显示 // 根据您的硬件设计,可能需要延时 Delay(1); } } ``` 5. 主循环问题: 在主循环中,确保您能够正确地根据标志位决定是否擦除扇区,并将通过串口接收的数据存入EEPROM。以下是一个示例: ```c void main() { UartInit(); // 初始化串口 // 初始化EEPROM // 初始化显示 while (1) { if (flag) { // 擦除EEPROM扇区 // 将通过串口接收的数据存入EEPROM flag = 0; // 重置标志位 } Display(); // 显示存储在数组中的数据 } } ``` 请根据您的具体需求和硬件设计,调整上述代码。希望这些建议能帮助您解决问题。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
852 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
592 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
705 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
926 浏览 2 评论
657 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11998 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 21:43 , Processed in 0.377247 second(s), Total 41, Slave 34 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号