51单片机IO口模拟串口遇到问题,请各样帮忙看下
时间:10-02
整理:3721RD
点击:
大家好,我是一个新人,最近在用51单片机做个东西,因为同时用到GSM模块与语音合成模块,但是串口不够用,想用IO口模拟串口,因为GSM比较复杂,又因为那个语音合成模块只需要用到发送串口,所以我想在单片机上模块一个发送串口,但是不知道为什么,程序在keil上显示是没有问题的,但是语音合成模块就是没有声音,也就是单片机发送不出来,各位大神能不能帮帮忙,解答一下(注:这个程序是结合例程与串口程序组合的 ,不知道可否)
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define KEY P1 //P1用于键扫描
sbit K0 = P1^0; //定义 K0 键,用于计数递增
sbit K1 = P1^1; //定义 K1 键,用于计数递减
#define TEXTLEN 13 //固定文字的长度
#define HEADLEN 5 //数据包头的长度
#define LEN_OFFSET 2 //长度字节的偏移量(本例中长度不超过255字节,因此只使用1字节长度)
sbit newTXD = P2^1;//模拟串口的发送端设为P2.1
//数据包头(0xFD + 2字节长度 + 1字节命令字 + 1字节命令参数)
uchar head[HEADLEN] = {0xfd,0x00,0x00,0x01,0x00};
//文字(中间有需要变化的内容可在发送前修改)
uchar text[TEXTLEN] = {"当前变量值为0"};
uchar val = 0; //计数值
uchar old = 0; //旧计数值(用来检测变化)
uchar xor = 0; //校验码(正文内容的异或)
int i;
uchar n,a;
//延时1ms
void Delay1ms(uchar n)
{
uchar i=112;
while(n--)
{
while(i--);
}
}
void UartInit()
{
SCON = 0x50; // SCON: serail mode 1, 8-bit UART
TMOD |= 0x21; // T0工作在方式1,十六位定时
PCON |= 0x80; // SMOD=1;
TH0 = 0xFE; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz
TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz
// TH0 = 0xFD; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz
// TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz
}
void WaitTF0(void)
{
while(!TF0);
TF0=0;
TH0=0xFE; // 定时器重装初值 fosc=11.0592MHz
TL0=0x7F; // 定时器重装初值 fosc=11.0592MHz
// TH0 = 0xFD; // 定时器重装初值 fosc=18.432MHz
// TL0 = 0x7F; // 定时器重装初值 fosc=18.432MHz
}
void WByte(uchar input) //发送数据
{
//发送启始位
uchar j=8;
TR0=1;
newTXD=(bit)0;
WaitTF0();
//发送8位数据位
while(j--)
{
newTXD=(bit)(input&0x01); //先传低位
WaitTF0();
input=input>>1;
}
//发送校验位(无)
//发送结束位
newTXD=(bit)1;
WaitTF0();
TR0=0;
}
/*/串口发送数据
void UART_Trans(uchar n)
{
SBUF = n;
while(TI==0); //发送数据
TI=0;
} */
/*void Sendata2(uchar *a)
{
for(i=0;i<sizeof(a);i++)//外层循环,遍历数组
{
WByte(a);
}
}
*/
void Sendata1()
{
for(i=0;i<sizeof(head);i++)//外层循环,遍历数组
{
WByte(head);
}
}
void Sendata2()
{
for(i=0;i<sizeof(text);i++)//外层循环,遍历数组
{
WByte(text);
}
}
/*void Sendata3()
{
for(i=0;i<sizeof(xor);i++)//外层循环,遍历数组
{
WByte(xor);
}
}*/
//键扫描
uchar keyScan(uchar n)
{
KEY = 0xff; //置位P2口以读取键值
if(K0 == 0) //如果 K0 键按下
{
Delay1ms(1); //消抖
if(K0 == 0) //确认按下
{
n++; //计数递增
}
while(K0 == 0); //等待按键抬起
}
if(K1 == 0) //如果 K1 键按下
{
Delay1ms(1); //消抖
if(K1 == 0) //确认按下
{
n--; //计数递减
}
while(K1 == 0); //等待按键抬起
}
return n % 10; //约束并返回计数值
}
//主函数
void main()
{
uchar i = 0; //循环计数变量
UartInit(); //初始化串口为 9600bps
while(1)
{
val = keyScan(val); //检查按键并提取计数值
if(val != old) //检查计数值变化
{
//如有变化则发送以下数据包
// head[] text[]
// |--------------------------|------------------------------------------|
// | FD | 00 10 | 01 00 | B5 B1 C7 B0 B1 E4 C1 BF D6 B5 CE AA | 30 | 83 |
// | 数据包头 | 长度 | 命令 | 当 前 变 量 值 为 | 0 | XOR校验码 |
// | |-->| 数据长度 |<--
// | |--------------------------------------------------------------|
xor = 0; //校验码初始化
head[LEN_OFFSET] = TEXTLEN + 3; //计算正文长度(1命令字 + 1命令参数 + 文字长度 + 1校验位)
//发送数据包头(0xFD + 2字节长度 + 1字节命令字 + 1字节命令参数)
for(i = 0; i < HEADLEN; i++)
{
xor ^= head;
Sendata1 ();
Delay1ms(2);
}
text[TEXTLEN-1] = val + '0'; //修改动态内容
//发送文字内容
for(i = 0; i < TEXTLEN; i++)
{
xor ^= text;
Sendata2 ();
Delay1ms(2);
}
WByte(xor); //发送校验位
old = val; //保存当前计数值用于检查
}
Delay1ms(100); //延时
}
}
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define KEY P1 //P1用于键扫描
sbit K0 = P1^0; //定义 K0 键,用于计数递增
sbit K1 = P1^1; //定义 K1 键,用于计数递减
#define TEXTLEN 13 //固定文字的长度
#define HEADLEN 5 //数据包头的长度
#define LEN_OFFSET 2 //长度字节的偏移量(本例中长度不超过255字节,因此只使用1字节长度)
sbit newTXD = P2^1;//模拟串口的发送端设为P2.1
//数据包头(0xFD + 2字节长度 + 1字节命令字 + 1字节命令参数)
uchar head[HEADLEN] = {0xfd,0x00,0x00,0x01,0x00};
//文字(中间有需要变化的内容可在发送前修改)
uchar text[TEXTLEN] = {"当前变量值为0"};
uchar val = 0; //计数值
uchar old = 0; //旧计数值(用来检测变化)
uchar xor = 0; //校验码(正文内容的异或)
int i;
uchar n,a;
//延时1ms
void Delay1ms(uchar n)
{
uchar i=112;
while(n--)
{
while(i--);
}
}
void UartInit()
{
SCON = 0x50; // SCON: serail mode 1, 8-bit UART
TMOD |= 0x21; // T0工作在方式1,十六位定时
PCON |= 0x80; // SMOD=1;
TH0 = 0xFE; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz
TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz
// TH0 = 0xFD; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz
// TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz
}
void WaitTF0(void)
{
while(!TF0);
TF0=0;
TH0=0xFE; // 定时器重装初值 fosc=11.0592MHz
TL0=0x7F; // 定时器重装初值 fosc=11.0592MHz
// TH0 = 0xFD; // 定时器重装初值 fosc=18.432MHz
// TL0 = 0x7F; // 定时器重装初值 fosc=18.432MHz
}
void WByte(uchar input) //发送数据
{
//发送启始位
uchar j=8;
TR0=1;
newTXD=(bit)0;
WaitTF0();
//发送8位数据位
while(j--)
{
newTXD=(bit)(input&0x01); //先传低位
WaitTF0();
input=input>>1;
}
//发送校验位(无)
//发送结束位
newTXD=(bit)1;
WaitTF0();
TR0=0;
}
/*/串口发送数据
void UART_Trans(uchar n)
{
SBUF = n;
while(TI==0); //发送数据
TI=0;
} */
/*void Sendata2(uchar *a)
{
for(i=0;i<sizeof(a);i++)//外层循环,遍历数组
{
WByte(a);
}
}
*/
void Sendata1()
{
for(i=0;i<sizeof(head);i++)//外层循环,遍历数组
{
WByte(head);
}
}
void Sendata2()
{
for(i=0;i<sizeof(text);i++)//外层循环,遍历数组
{
WByte(text);
}
}
/*void Sendata3()
{
for(i=0;i<sizeof(xor);i++)//外层循环,遍历数组
{
WByte(xor);
}
}*/
//键扫描
uchar keyScan(uchar n)
{
KEY = 0xff; //置位P2口以读取键值
if(K0 == 0) //如果 K0 键按下
{
Delay1ms(1); //消抖
if(K0 == 0) //确认按下
{
n++; //计数递增
}
while(K0 == 0); //等待按键抬起
}
if(K1 == 0) //如果 K1 键按下
{
Delay1ms(1); //消抖
if(K1 == 0) //确认按下
{
n--; //计数递减
}
while(K1 == 0); //等待按键抬起
}
return n % 10; //约束并返回计数值
}
//主函数
void main()
{
uchar i = 0; //循环计数变量
UartInit(); //初始化串口为 9600bps
while(1)
{
val = keyScan(val); //检查按键并提取计数值
if(val != old) //检查计数值变化
{
//如有变化则发送以下数据包
// head[] text[]
// |--------------------------|------------------------------------------|
// | FD | 00 10 | 01 00 | B5 B1 C7 B0 B1 E4 C1 BF D6 B5 CE AA | 30 | 83 |
// | 数据包头 | 长度 | 命令 | 当 前 变 量 值 为 | 0 | XOR校验码 |
// | |-->| 数据长度 |<--
// | |--------------------------------------------------------------|
xor = 0; //校验码初始化
head[LEN_OFFSET] = TEXTLEN + 3; //计算正文长度(1命令字 + 1命令参数 + 文字长度 + 1校验位)
//发送数据包头(0xFD + 2字节长度 + 1字节命令字 + 1字节命令参数)
for(i = 0; i < HEADLEN; i++)
{
xor ^= head;
Sendata1 ();
Delay1ms(2);
}
text[TEXTLEN-1] = val + '0'; //修改动态内容
//发送文字内容
for(i = 0; i < TEXTLEN; i++)
{
xor ^= text;
Sendata2 ();
Delay1ms(2);
}
WByte(xor); //发送校验位
old = val; //保存当前计数值用于检查
}
Delay1ms(100); //延时
}
}
先确定是哪个问题,硬件还是软件的问题
硬件分开测试是没有问题的