|
由于9234只有一个通讯口,所以在需要多个通讯口的场合就很不方便,换芯片的话成本就会增加很多,所以就研究了模拟串口的方法。
在该方案中,波特率采用4800,1位起始位,8位数据位,偶校验,两位停止位,波特率是用定时器来控制的,经过测试,在常温和70度左右的情况下,通讯出错率均小于1%。基于硬件限制,收发数据依然采用P43,P44口,该口工作于I/O端口状态
希望这个程序对大家有用。
欢迎大家加我的QQ:386132185,留言说明是在学习nec的,我们可以互相学习,共同提高
另欢迎大家加入 12580452 QQ群。
由于本人经验有限,程序中难免会有缺陷,欢迎大家拍砖。
点击此处下载 ourdev_571508.pdf(文件大小:59K) (原文件名:9234模拟串口通讯.pdf)
/*******************************************************************************
//功能: 模拟UART,当芯片自身的通讯口有限时,可以用该方法模拟通讯
//数据模式: 波特率:4800,1位起始位,8位数据位,偶校验,2位停止位,
// 经过测试,通讯出错率小于1%
// 基于硬件限制,该程序中用于模拟通讯的口仍选择P43,P44口,P43,P44口
// 工作在I/O口状态
//作者: 范 坤
//公司: 上海耘和空调科技有限公司
//完成日期: 2010.07.28
*******************************************************************************/
#include<io78f9234.h>
#include<intrinsiCS.h>
/*--------------------选项字节配置------------------------*/
/*-----------------------------------------------------------
内部时钟,
-----------------------------------------------------------*/
#pragma location = 0X0080
__root const unsigned char XUAN=0X9c;//选项字节,设置实用内部高速时钟电路,低速内部振荡器时钟可由软件停止
#define uchar unsigned char
#define uint unsigned int
#define ushort unsigned short
/*以下声明是对寄存器的操作,分别对寄存器的某一位清零或置一*/
#define clearbit(Reg, ClrBitMap) Reg &= ~ClrBitMap//清零操作
#define setbit(Reg, SetBitMap) Reg |= SetBitMap//置1操作
#define DI() __disable_interrupt()//屏蔽所有中断
#define EI() __enable_interrupt()//使能所有中断
#define NOP() __no_operation()//空操作
#define P00 P0_bit.no0
#define P01 P0_bit.no1
#define P02 P0_bit.no2
#define P03 P0_bit.no3
#define P120 P12_bit.no0
#define P121 P12_bit.no1
#define P122 P12_bit.no2
#define P123 P12_bit.no3
#define P130 P13_bit.no0
#define P20 P2_bit.no0
#define P21 P2_bit.no1
#define P22 P2_bit.no2
#define P23 P2_bit.no3
#define P30 P3_bit.no0
#define P31 P3_bit.no1
#define P32 P3_bit.no2
#define P33 P3_bit.no3
#define P40 P4_bit.no0
#define P41 P4_bit.no1
#define P42 P4_bit.no2
#define P43 P4_bit.no3
#define P44 P4_bit.no4
#define P45 P4_bit.no5
#define P46 P4_bit.no6
#define P47 P4_bit.no7
#define TXD P4_bit.no3
#define RXD P4_bit.no4
__saddr uchar sendbuffer[4];//发送缓存
__saddr uchar recbuffer[4];//接收缓存
__saddr uchar rxd_count;//该组参数用于记录接收或发送的数据的位数
void clock();//时钟初始化函数
void PORT_Init();//端口初始化函数
void TMH1_Init();//定时器初始化函数
void main();//主函数
void TMH1_Start();//启动定时器函数
void TMH1_Stop();//停止定时器函数
void delayms(uint ms);//准确延时1ms,当ms=1时
void send_data(uchar data);//发送数据函数
uchar rec_data();//接收数据函数,返回值为接收到数据的内容
/****简单延时函数,在该延时函数中,当ms=1时,可以准确实现延时1ms***************/
void delayms(uint ms)//准确延时1ms,当ms=1时
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<460;j++);
}
/**********************时钟初始化函数,系统时钟为8MHz***************************/
void clock()
{
PPCC=0X00;
PCC=0X00;
}
/******************************端口初始化函数**********************************/
void PORT_Init(void)
{
clearbit(PM3,0X02);//P31设定为输出口
clearbit(PM4,0X28);//P43,P45设定为输出口
setbit(PM4,0X10);//P44设定为输入口
setbit(P4, 0x08); /* port setting in transmit/receive mode */
PM2=0X00;
}
/********************定时器初始化函数,定时204us,实现4800波特率***************/
void TMH1_Init(void)
{
TMHE1 = 0; /* disable TMH1 counter */
TMMKH1 = 1; /* disable INTTMH1 */
TMIFH1 = 0; /* enable INTTMH1 */
/* TMH1 interval mode */
TMHMD1 = 0x20;
CMP01 = 0x68;
}
/***************************启动定时器函数*************************************/
void TMH1_Start(void)
{
TMHE1 = 1; /* enable TMH1 counter */
}
/***************************停止定时器函数*************************************/
void TMH1_Stop(void)
{
TMHE1 = 0; /* disable TMH1 counter */
}
/********************************发送数据函数**********************************/
void send_data(uchar data)
{
uchar txd_count=0;//该参数用于记录发送数据的位数
uchar even_count=0;//该参数用于记录发送的数据位1的位数,从而判断发送的偶校验位的值
P31=1;//发送数据使能
NOP();
/*************发送起始位,1位起始位,低电平***********/
TXD=0;
TMH1_Start();//开定时器中断
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
/*************发送数据位,8位数据位***********/
while(txd_count<8)
{
if(data&0x01)
{
TXD=1;
even_count++;
}
else
TXD=0;
TMH1_Start();//开定时器中断
while(!TMIFH1)
NOP();
TMIFH1=0;
txd_count++;
data=data>>1;
}
/*************发送校验位,在该系统中采用偶校验的方式***********/
if(even_count%2) TXD=1;
else TXD=0;
while(!TMIFH1)
NOP();
TMIFH1=0;
TMH1_Start();//开定时器中断
/*************发送停止位,两位停止位***********/
TXD=1;
while(!TMIFH1)
NOP();
TMIFH1=0;
TMH1_Start();//开定时器中断
TXD=1;
while(!TMIFH1)
NOP();
TMIFH1=0;
TMH1_Stop();
}
/********************************接收数据函数**********************************/
uchar rec_data()
{
uchar data=0xff;//该参数用于记录接收到的数据
uchar rxd_count=8;//该参数用于记录接收数据的位数
uchar even_count=0;//该参数用于记录发送的数据位1的位数,从而判断发送的偶校验位的值
uchar even;//该参数用于存储接收到的校验位
uchar a,b;//该组参数用于存储接收到的停止位
P31=0;//接收数据使能
while(RXD&0X01)//等待起始位
{
NOP();
}
CMP01 = 0x9c;//错后半位,抗干扰
TMH1_Start();//开定时器中断
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
while(rxd_count)
{
data>>=1;//低位在前传送
if(RXD)
{
data=data|0X80;
even_count++;
}
else
{
data=data|0X00;
}
CMP01 = 0x68;//保持错后半位检测
TMH1_Start();//开定时器中断
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
rxd_count--;
}
even=RXD;//接收到的校验位
TMH1_Start();//开定时器中断
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
a=RXD;
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
b=RXD;
while(!TMIFH1) //没有产生中断就等待
NOP();
TMIFH1=0;
TMH1_Stop();
recbuffer[0]=data;
if(even&&a&&b)
return 0;
else
return 1;
}
/************************************主函数*************************************/
void main()
{
DI();//关总中断
LSRSTOP=0x01;//停止低速内部振荡器
WDTM=0X77;//屏蔽看门狗
clock();//时钟初始化
PORT_Init();//端口初始化
TMH1_Init();//定时器初始化
EI();//开总中断
while(1)
{
rec_data();
send_data(recbuffer[0]);
delayms(10);
/*------------------------
for(uchar i=0;i<8;i++)
{
P45=recbuffer[0]&0x01;
recbuffer[0]=recbuffer[0]>>1;
delayms(10);
}
-----------------------*/
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|