AT89S52单片机并行转串行c语言程序

 我来答
5iDIY
2012-01-13 · TA获得超过469个赞
知道小有建树答主
回答量:652
采纳率:100%
帮助的人:192万
展开全部
在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。经过若干曲折并参考了一些现有的资料,基本上完成了。现在将完整的测试程序,以及其中一些需要总结的部分贴出来。

程序硬件平台:11.0592M晶振,

/***************************************************************
* 在单片机上模拟了一个串口,使用P2.1作为发送端
* 把单片机中存放的数据通过P2.1作为串口TXD发送出去
***************************************************************/
#include <reg51.h>
#include <stdio.h>
#include <string.h>

typedef unsigned char uchar;

int i;

uchar code info[] =
{
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
};

sbit newTXD = P2^1;//模拟串口的发送端设为P2.1

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 Sendata()
{
for(i=0;i<sizeof(info);i++)//外层循环,遍历数组
{
WByte(info[i]);
}
}

void main()
{
UartInit();
while(1)
{
Sendata();
}
}
##############################################################################

/***************************************************************
* 模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际串口
* 在单片机上模拟了一个串口,使用P3.2作为发送和接收端
* 以P3.2模拟串口接收端,从模拟串口接收数据发至串口
***************************************************************/
#include<reg51.h>
#include<stdio.h>
#include<string.h>

typedef unsigned char uchar ;

//这里用来切换晶振频率,支持11.0592MHz和18.432MHz
//#define F18_432
#define F11_0592
uchar tmpbuf2[64]={0};
//用来作为模拟串口接收数据的缓存

struct
{
uchar recv :6 ;//tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中
uchar send :6 ;//tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口
}tmpbuf2_point={0,0};

sbit newRXD=P3^2 ;//模拟串口的接收端设为P3.2

void UartInit()
{
SCON=0x50 ;// SCON: serail mode 1, 8-bit UART
TMOD|=0x21 ;// TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1,十六位定时
PCON|=0x80 ;// SMOD=1;

#ifdef F11_0592
TH1=0xE8 ;// Baud:2400 fosc=11.0592MHz 2400bps为从串口接收数据的速率
TL1=0xE8 ;// 计数器初始值,fosc=11.0592MHz 因为TH1一直往TL1送,所以这个初值的意义不大
TH0=0xFF ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz
TL0=0xA0 ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz
#endif

#ifdef F18_432
TH1=0xD8 ; // Baud:2400 fosc=18.432MHz 2400bps为从串口接收数据的速率
TL1=0xD8 ; // 计数器初始值,fosc=18.432MHz 因为TH1一直往TL1送,所以这个初值的意义不大
TH0=0xFF ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz
TL0=0x60 ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz
#endif

IE|=0x81 ;// 中断允许总控制位EA=1;使能外部中断0
TF0=0 ;
IT0=1 ;// 设置外部中断0为边沿触发方式
TR1=1 ;// 启动TIMER1,用于产生波特率
}

void WaitTF0(void)
{
while(!TF0);
TF0=0 ;

#ifdef F11_0592
TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz
TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz
#endif

#ifdef F18_432
TH0=0xFF ;
// 定时器重装初值 fosc=18.432MHz
TL0=0x60 ;
// 定时器重装初值 fosc=18.432MHz
#endif
}

//接收一个字符
uchar RByte()
{
uchar Output=0 ;
uchar i=8 ;
TR0=1 ; //启动Timer0

#ifdef F11_0592
TH0=0xFF ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz
TL0=0xA0 ;// 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz
#endif

#ifdef F18_432
TH0=0xFF ;// 定时器重装初值 fosc=18.432MHz
TL0=0x60 ;// 定时器重装初值 fosc=18.432MHz
#endif

TF0=0 ;

WaitTF0();//等过起始位
//接收8位数据位
while(i--)
{
Output>>=1 ;
if(newRXD)Output|=0x80 ;//先收低位
WaitTF0();//位间延时
}

TR0=0 ;//停止Timer0
return Output ;
}

//向COM1发送一个字符
void SendChar(uchar byteToSend)
{
SBUF=byteToSend ;
while(!TI);
TI=0 ;
}

void main()
{
UartInit();
while(1)
{
if(tmpbuf2_point.recv!=tmpbuf2_point.send)//差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理(发送至串口)
{
SendChar(tmpbuf2[tmpbuf2_point.send++]);
}
}
}

//外部中断0,说明模拟串口的起始位到来了
void Simulated_Serial_Start()interrupt 0
{
EX0=0 ; //屏蔽外部中断0
tmpbuf2[tmpbuf2_point.recv++]=RByte(); //从模拟串口读取数据,存放到tmpbuf2数组中
IE0=0 ; //防止外部中断响应2次,防止外部中断函数执行2次
EX0=1 ; //打开外部中断0
}

51单片机超声波DIY
自由飞翔就是我
2012-01-10 · TA获得超过467个赞
知道小有建树答主
回答量:226
采纳率:37%
帮助的人:106万
展开全部
Px.x=(data>>1) && 0x01
问题简单~
追问
谢谢您,但我需要完整的C语言程序
追答
你理解了这一条就足够了,除非你对问题还有进一步的要求,或者你的单片机程序还没有运行起来?
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2012-01-11
展开全部
165
追问
对!
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
a451993547
2012-01-09 · TA获得超过1593个赞
知道小有建树答主
回答量:595
采纳率:100%
帮助的人:700万
展开全部
是74HC165芯片吗?
追问
嗯 是的
追答
并转串
可以用串口工作方式0
还有模拟的方法
unsigned char send165(void)
{
unsigned char i,temp=0;
SH=0;
SH=1;
CLKIN=0;
for(i=0;i<8;i++)
{
CLK=0;
temp<<=1;
if(DQ)
temp++;
CLK=1;
}
CLKIN=1;
return temp;
}
本回答被提问者和网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式