想做一个电子名牌,上位机端大致已经弄好,现在单片机端程序还有问题。程序首先读取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; // 清除接收标志位
}
}
stc15f2k60s2利用串口传输字模存储到eeprom并进行点阵显示
关键词: stc15f2k60s2 串口 传输 字模 点阵
您的代码中有一些关键部分没有提供,例如点阵显示宏定义、串口初始化和中断服务程序等。因此,我将基于您提供的信息,给出一些可能的问题和解决方案。
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(); // 显示存储在数组中的数据
}
}
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 | |
【分享评测,赢取加热台】使用8051单片机驱动WS2812被打赏40分 | |
【换取逻辑分析仪】rtthread添加RRH62000传感器驱动-基于野火启明6M5被打赏48分 | |
换逻辑分析仪+Verilog多输入门被打赏27分 |