发一个通用的I-O模拟串口程序(适用于任何带有定时器的单片机)

合集下载

STC12C5AIO模拟I2C2014523c文件

STC12C5AIO模拟I2C2014523c文件
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
#endif
}
//**************************************
//I2C起始信号
//**************************************
/***************************************************************************
* 头文件
****************************************************************************/
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
* 功能: 延时
* 输入:
* 输出:
***************************************************************************/

51单片机串口通信实例

51单片机串口通信实例

51单片机串口通信实例一、原理简介51 单片机内部有一个全双工串行接口。

什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。

串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。

其缺点是传输速度较低。

与之前一样,首先我们来了解单片机串口相关的寄存器。

SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。

从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。

串行口控制寄存器SCON(见表1) 。

表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。

SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。

经验分享:学习单片机重要的是实践,所以开发板是很重要,给大家推荐些淘宝上信誉良好并且软硬件及小零件等、售前售后服务良好的皇冠级金钻店铺给大家,在硬件购买上少走弯路。

按住Ctrl键单击即可:慧净电子单片机(一皇冠)【天津商盟】天津锐志(电子)单片机经营部(两皇冠)金沙滩工作室(5钻)深圳育松电子元件,模块,传感器,批发部:淘宝最全最平价(5皇冠)志宏电子(4钻)表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。

SM2 :多机通信控制位。

该仅用于方式2 和方式3 的多机通信。

其中发送机SM2 = 1(需要程序控制设置)。

接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。

当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。

51单片机模拟spi串行接口程序

51单片机模拟spi串行接口程序
unsigned char SPI_TransferByte(unsigned char val)
{
unsigned char BitCounter;
for(BitCounter=8; BiCounter!=0; BitCounter--)
{ CLK=0;
DataI=0; // write
if(val&0x80) DataI=1;
val<<=1;
CLK=1;
if(DataO)val|=1; // read
}
CLK=0;
return val;
}
sbit CLK= P1^5;
sbit DataI=P1^7;
sbiபைடு நூலகம் DataO=P1^6;
#define SD_Disable() CS=1 //片选关
#define SD_Enable() CS=0 //片选开
val<<=1;
CLK=1;
if(DataO)val|=1; // read
}
CLK=0;
return val;
}
sbit CLK= P1^5;
sbit DataI=P1^7;
sbit DataO=P1^6;
#define SD_Disable() CS=1 //片选关
#define SD_Enable() CS=0 //片选开
unsigned char SPI_TransferByte(unsigned char val)
{
unsigned char BitCounter;
for(BitCounter=8; BiCounter!=0; BitCounter--)
{ CLK=0;

如何使用单片机的单个IO口模拟串口UART输出

如何使用单片机的单个IO口模拟串口UART输出
if(பைடு நூலகம்at & BIT(i)) {
IO_UART_TX_H(); } else {
IO_UART_TX_L(); asm("l.nop");//延时一个机器周期 } delay_one_bit_tx(); } IO_UART_TX_H();//发送结束位 delay_one_bit_tx(); }
1
V1.0
模拟的串口协议如下:
起始位 1 位 数据位 8 位 停止位 1 位 校验位 无
参考的代码如下:
void io_uart_send_byte(unsigned char dat) {
Unsigned char i ; IO_UART_TX_L();//拉低作为起始 delay_one_bit_tx();//按照需要的波特率来延时 for(i = 0 ; i< 8 ; i++) {
普通 MCU 模拟串口发送说明
相关说明:
(1)、模拟 115200 波特率,信号跳变的时间为 8.68uS = 1 / 115200 (2)、模拟 9600 波特率,信号跳变的时间为 104.1uS = 1 / 9600 (3)、串口的波特率越高,所需要的时间越短,相对稳定性越差,建议采用 9600 波特率。 (4)、串口的发射模拟相对比较容易,接收比较困难。下面就串口的 IO 模拟发射做说明 (5)、我们的串口允许的时钟误差最多 3%。所以用户请严格的控制时间误差在这个范围。

运用4个普通IO口模拟SPI程序等

运用4个普通IO口模拟SPI程序等
SIG--------- PORTB.0 双项输入 Din--------- PORTB.2 单项输出 Dout-------- PORTB.3 双项输入 SCLK-------- PORTB.4 单项输出 CS---------- PORTB.5 单项输出 SEL--------- PORTB.6 单项输出 RESET------- PORTB.1 单项输出 #define SET1302_RST PORTB|=(1<<7) #define CLR1302_RST PORTB&=~(1<<7) ************************************************************* ************************/ #define ATT_SIG PINB.0 #define ATT_Din PORTB.2 #define ATT_Dout PINB.3 #define ATT_SCLK PORTB.4
运用 4 个普通 I/O 口模拟 SPI 程序源代码
/******************************************************************** 函 数 名:uchar SpiReadWrite(uchar dat) 功 能:SPI 发送接收一个数据 说 明: 调 用: 入口参数: 出口参数: ***********************************************************************/ uchar SpiReadWrite(uchar dat) { uchar i,temp; temp=0; SCK=0; _nop_(); for(i=0;i<8;i++) { if(dat & 0x80) { MOSI=1; }

简单好用的stc12c5a串口2发送程序!

简单好用的stc12c5a串口2发送程序!

//功能:stc12c5a串口2发送程序,发送0--9,晶振频率11.0592MHz,串行口工作于方式1,波特率为9600#ifndef __STC12C5A60S2_H__#define __STC12C5A60S2_H__//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机内核特殊功能寄存器 C51 Core SFRs// 7 6 5 4 3 21 0 Reset Valuesfr ACC = 0xE0; //Accumulator 0000,0000sfr B = 0xF0; //B Register 0000,0000sfr PSW = 0xD0; //Program Status Word CY AC F0 RS1 RS0 OVF1 P 0000,0000//-----------------------------------sbit CY = PSW^7;sbit AC = PSW^6;sbit F0 = PSW^5;sbit RS1 = PSW^4;sbit RS0 = PSW^3;sbit OV = PSW^2;sbit P = PSW^0;//-----------------------------------sfr SP = 0x81; //Stack Pointer 0000,0111sfr DPL = 0x82; //Data Pointer Low Byte 0000,0000sfr DPH = 0x83; //Data Pointer High Byte 0000,0000//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机系统管理特殊功能寄存器// 7 6 5 4 3 21 0 Reset Valuesfr PCON = 0x87; //Power Control SMOD SMOD0 LVDF POF GF1 GF0 PDIDL 0001,0000// 7 6 5 4 3 21 0 Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS 0000,0000//-----------------------------------sfr AUXR1 = 0xA2; //Auxiliary Register 1 - PCA_P4 SPI_P4 S2_P4 GF2 ADRJ -DPS 0000,0000/*PCA_P4:0, 缺省PCA 在P1 口1,PCA/PWM 从P1 口切换到P4 口: ECI 从P1.2 切换到P4.1 口,PCA0/PWM0 从P1.3 切换到P4.2 口PCA1/PWM1 从P1.4 切换到P4.3 口SPI_P4:0, 缺省SPI 在P1 口1,SPI 从P1 口切换到P4 口: SPICLK 从P1.7 切换到P4.3 口MISO 从P1.6 切换到P4.2 口MOSI 从P1.5 切换到P4.1 口SS 从P1.4 切换到P4.0 口S2_P4:0, 缺省UART2 在P1 口1,UART2 从P1 口切换到P4 口: TxD2 从P1.3 切换到P4.3 口RxD2 从P1.2 切换到P4.2 口GF2: 通用标志位ADRJ:0, 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器1,10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器DPS: 0, 使用缺省数据指针DPTR01,使用另一个数据指针DPTR1*///-----------------------------------sfr WAKE_CLKO = 0x8F; //附加的 SFR WAK1_CLKO/*7 6 5 4 3 2 1 0 Reset ValuePCAWAKEUP RXD_PIN_IE T1_PIN_IE T0_PIN_IE LVD_WAKE _ T1CLKO T0CLKO 0000,0000Bb7 - PCAWAKEUP : PCA 中断可唤醒 powerdown。

51单片机GPIO口模拟串口通信

51单片机GPIO口模拟串口通信

51单片机GPIO口模拟串口通信随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。

这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51 系列只提供一个串口,那么另一个串口只能靠程序模拟。

本文所说的模拟串口,就是利用51的两个输入输出引脚P1.0 和P1.1,置1 或0 分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况置1 或置0。

以11.0592MHz 的晶振为例,通过定时计数器0 产生中断信号来模拟串口电平,下面附上具体源代码。

[cpp]view plaincopy/*Fuction:使用51 单片机GPIO 口模拟串口通信,通过定时计数器0 来产生中断信号SoftwareDesigner:Jason*/#includesbitP1_0=P1;sbitP1_1=P1;#de fine RXD P1_0#de fineTXDP1_1unsignedcharflag;voidinit();voidsend_byte(unsignedchar);unsignedchar rec_byte();voidwait_int();//将从PC 机串口接收到的数据原封不动回传给PC 机voidmain(){unsignedchartemp;init();while(1){if(RI==1){RI=0;temp=rec_byte();send_byte(temp);while(!TI);TI=0;}}}//端口及中断初始化voidinit(){TMOD=0x02;//定时器0,方式2TH0=0xfd;//波特率9600TL0=TH0;TR0=0;//在发送或接收时打开ET0=1;//允许定时器0 中断EA=1;//允许所有中断}//通过串口发送一个字节数据voidsend_byte(unsignedchardat){unsignedchari=8;TR0=1;//开启T0 中断TXD=0;//发送起始位0wait_int();while(i--)//发送8 位数据{TXD=(bit)(dat&0x01);wait_int();dat=dat>>1;}TXD=1;//发送停止位1wait_int();TR0=0;//关闭T0 中断}//通过串口。

51单片机串口工作方式0和1

51单片机串口工作方式0和1

ACALL DELAY
CLR TI
; 手动清中断标志
RR A ; 循环位移
; 80H、40H、20H、10H、08H …
CLR P1.0
; CD4094 输出并口关闭
MOV SBUF,A ; 数据传出,产生中断
RETI
END
注: 延时子程序 DELAY 未给出
2021/5/15
方式 0 用于扩展并行 I/O口
=
/32
9600bps 1200bps
=
/12/计次/16
计1次 计3次 计3次 计6次 计12次 计24次
9.6kbit/s 实际10.416 = 6MHz/12/计次/16 1
0
2
FDH
1.2kbit/s 实际1.302 = 6MHz/12/计次/32 0
0
2
F4H
时钟振荡频率为6MHz或12 MHz时,产生的比特率偏差较大,
写入SBUF后自动开始发 送
2021/5/15
图5-1
请求中断
CPU响应中断后:CLR TI
5.2 用AT89C51的串行口扩展并行口
5.2.2 用74LS164扩展并行输出口
74LS164:8位串入并出移位寄存器。
图是利用74LS164扩展二个8位并行输出口的接口电路。

每当新数据写入SBUF,即把SBUF中的8位数据以串行移
• 数据区
发送数据区首址 20H,接收数据区首址 40H
• 主频选用
fosc = 6MHz
• T1 设置
,同时RI=0)时,串行口即开始接收数据。RXD为数据输入端
,TXD为移位脉冲信号输出端,也以fosc/12的固定比特率,

51单片机串口通信程序。。含详细例子

51单片机串口通信程序。。含详细例子

{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} void serial () interrupt 4 using 3 //串口接收中断函数 {
if (RI) { RI = 0 ; ch=SBUF; read_flag= 1 ; //就置位取数标志 }
} main()
{ init_serialcom(); //初始化串口 while ( 1 ) { if (read_flag) //如果取数标志已置位,就将读到的数从串口发出 { read_flag= 0 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();

用AVR单片机IO口模拟I2C总线操作AT24CXX的通用程序

用AVR单片机IO口模拟I2C总线操作AT24CXX的通用程序
twi_ack(ack);
*c=ret;
return(ret);
}
以下为AT24CXX的操作函数实现:
at24cxx.h:
//AT24CXX.H
#ifndef AT24CXX_H
#define AT24CXX-H
void At24cxxWaitBusy(void);
#include <util/delay.h>
#include <stdint.h>
/*注:
AVR单片机I/O口模拟I2C总线时建议在外部连接上拉电阻
这样可通过改变I/O口输入输出方向的方式来设置高低
输出口保持不变(0)
此时如DDRX寄存器为1则变成输出0
若DDRX为0,则I/O口程高阻,但因外部的上拉电阻,总线相当于设置高
#define TW_READ 1
#define TW_ACK 1
#define TW_NOACK 0
Hale Waihona Puke /*以下两个宏控制AT24CXX的WP引脚,如未连接可定义为空:
#define EEPROM_WRITE_ENABLE
#define EEPROM_WRITE_DISABLE
AT24CXX中WP引脚接地时写允许,接电源(高)时写保护,
如不接,器件内部有接地电阻,即写允许. */
//在CA-M8X板上该引脚通过S7(3)连接MEGA8的PC3
#define EEPROM_WRITE_ENABLE PORTC&=~_BV(PC3),DDRC|=_BV(PC3)
void At24cxxConfig(uint8_t device_addr,uint8_t page_size);

51单片机模拟串口的三种方法

51单片机模拟串口的三种方法

//先传低位
} //查询计数器溢出标志位 void WaitTF0( void ) { while(!TF0); TF0=0; } 接收的程序,可以参考下一种方法,不再写出。这种办法个人感觉不错,接收和 都很准确,另外不需要计算每条语句的指令周期数。 方法三:中断法
中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户 在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程 断进行初始化,同时编写中断程序。本程序使用Timer0中断。 #define TM0_FLAG P1_2 //设传输标志位 //计数器及中断初始化 void S2INI(void) { TMOD =0x02; //计数器0,方式2 TH0=0xA0; //预值为256-96=140,十六进制A0 TL0=TH0; TR0=0; //在发送或 接收才开始使用 TF0=0; ET0=1; //允许定时
//发送启始
位 Delay2cp(39); //发送8位数据位 while(i--) { TXD=(bit)(input&0x01); Delay2cp(36); input=input>>1; } //发送校验位(无) TXD=(bit)1; 位 Delay2cp(46); } //从串口读一个字节 uchar RByte(void) { uchar Output=0; uchar i=8; uchar temp=RDDYN; //发送8位数据位 Delay2cp(RDDYN*1.5); while(i--) { Output >>=1; if(RXD) Output Delay2cp(35); 占用26个指令周期 } while(--temp) 时间内搜寻结束位。 { Delay2cp(1); if(RXD)break; } return Output;

IO口模拟232测试程序

IO口模拟232测试程序

/********************************************************* IO口模拟232测试程序,仿单片机Keil Cx51应用开发技术中的程序主要的功能是在利用串口调试工具发送一个8bit的数据,而后单片机接收后把这个数据发送给模拟串口*********************************************************/ #include "STC12C2052AD.H"sbit Tx_Pin=P3^7;//发送端口sbit Rx_Pin=P1^0;//接收端口sbit Baud0=P1^6;sbit Baud1=P1^7;//波特率选择bit Flag=0;//若标志位为1,则表示串口已经过了一位的时间#define unchar unsigned char#define unint unsigned intunchar HighTime;unchar LowTime;/********************************************************/ bit CheckA vailStartBit()//检测开始位{return(Rx_Pin==0);//若为0,则返回1,即有数据传送//若为1,则返回0,即没有接收到数据}/********************************************************/ void Timer0() interrupt 1//定时器中断处理{Flag=1;TL0=LowTime;TH0=HighTime;}/********************************************************/ unchar ReceiveByte()//接收字节{unchar Data;unint i;Data=0x00;TR0=1;//开始定时while(Flag==0);Flag=0;//开始位不采样for(i=0;i<=7;i++){Data>>=1;//移位处理if(Rx_Pin==1)//为1的话,则进行处理{Data|=0x80;}while(Flag==0);//若Flag为0,则时间还未到,等待//若Flag为1,则一位的时间已经到,准备接收数据Flag=0;}while(Flag==0);//对第9位停止位的处理Flag=0;while(Flag==0){if(Rx_Pin)//检测到停止位,退出{break;}}TR0=0;//关闭定时器return(Data);//返回数据}/********************************************************/void SendByte(unchar Data){unint i;TR0=1;//开始定时Tx_Pin=0;//起始位,0while(Flag==0);Flag=0;for(i=0;i<=7;i++){if(Data&0x01){Tx_Pin=1;}else{Tx_Pin=0;}Data>>=1;while(Flag==0);Flag=0;}Tx_Pin=1;//结束位TR0=0;//关闭定时器}/********************************************************/void main(){unchar temp;TMOD=0x01;//定时器0为模式1,自动重装载TR0=0;PCON=0x00;if(Baud1==1){if(Baud0==1){HighTime=0xFF;LowTime=0xD0;//在这个分频下波特率为19200}else{HighTime=0xFF;LowTime=0xA0;//在这个分频下波特率为9600,也是默认的波特率}}else{if(Baud0==0){HighTime=0xFF;LowTime=0x40;//在这个分频下波特率为4800}else{HighTime=0xFE;LowTime=0x80;//在这个分频下波特率为2400}}/********************测试*********************************/HighTime=0xFF;LowTime=0xA0;//在这个分频下波特率为9600,也是默认的波特率/*********************************************************/ TH0=HighTime;TL0=LowTime;ET0=1;//开定时器0的中断EA=1;//开总中断for(;;){if(CheckA vailStartBit())//模拟接收口检测到起始位{temp=ReceiveByte();//接收数据SendByte(temp);//将接收到的数据发送给PC }}}。

msp430g2553串口通信

msp430g2553串口通信

MSP430g2553串口通信MSP430的不同型号,其串行通讯工作模式是一样的。

以MSP430G2553为例进行说明。

MSP430G2553是20个引脚的16位单片机。

具有内置的16位定时器、16k 的FLASH 和512B 的RAM ,以及一个通用型模拟比较器以及采用通用串行通信接口的内置通信能力。

此外还具有一个10位的模数(A/D)转换器。

其引脚排布如图1.1所示。

其功能表如表1.1所示。

串行通讯模块主要由三个部分组成:波特率生成部分、发送控制器以及接收控制器。

如图1.2所示。

一、UART 模式在异步模式下,接收器自身实现帧的同步,外部的通讯设备并不使用这一时钟。

波特率的产生是在本地完成的。

异步帧格式由1个起始位、7或8个数据位、校验位(奇/偶/无)、1个地址位、和1或2个停止位。

一般最小帧为9个位,最大为13位。

图1.2 串行通讯模块内部结构图图1.1 MSP430G2553引脚图(一)UART的初始化单片机工作的时钟源来自内部三个时钟或者外部输入时钟,由SSEL1、SSEL0,以决定最终进入模块的时钟信号BRCLK的频率。

所以配置串行通讯的第一步就是选择时钟。

通过选择时钟源和波特率寄存器的数据来确定位周期。

所以波特率的配置是串行通讯中最重要的一部分。

波特率设置用三个寄存器实现:UxBR0(选择控制器0):波特率发生器分频系数低8位。

UxBR1(选择控制器1):波特率发生器分频系数高8位。

UxMCTL 数据传输的格式,以及数据传输的模式是通过配置控制寄存器UCTL来进行设置。

接收控制部分和发送控制部分。

首先需要串行口进行配置、使能以及开启中断。

串口接收数据一般采用中断方式,发送数据采用主动发送。

当接收到一个完整的数据,产生一个信号:URXIFG0=1(类似于51单片机的接收中断标志位),表示接收完整的数据。

当数据正在发送中,UTXIFG0=1,此时不能再发送数据,必须等当前数据发送完毕(UTXIFG0=0)才能进行发送。

STM8L101F3P6单片机IO模拟收发调试

STM8L101F3P6单片机IO模拟收发调试

本程序选用的芯片为STM8L101F3P6共分为如下几个文件Main.c文件内容#include "stm8l10x_diy_time.h"#include "stm8l10x_diy_port.h"#include "STM8L101F3P.h"#include "NRF24L01.h"#include "STM8l10x.h"char lock_key;void main(void){clk_init ();//时钟初始化gpio_init();time_init();LED01=0;LED02=0;IRQ_OUT;//IRQ设置为输出模式IRQ_O=1;//赋值ifnnrf_rx_mode();while (1){if(But01==0){ IRQ_OUT;IRQ_O=1;SPI_RW_Reg(WRITE_REG+STATUS,0xff);tx_buf[0]=2;ifnnrf_tx_mode();IRQ_IN;while(IRQ_I);sta=SPI_Read(STATUS);SPI_RW_Reg(WRITE_REG+STA TUS,0xff);if(sta& STA_MARK_TX){LED02=1;Delay(0xfffFf);LED02=0;Delay(0xffFff);}else{ifnnrf_CLERN_ALL();LED02=1;Delay(0xffFf);LED02=0;Delay(0xffFf);}ifnnrf_rx_mode();IRQ_OUT;IRQ_O=1;IRQ_IN;Delay(0x0f);while(IRQ_I==0);Delay(0xffff);}IRQ_OUT;IRQ_O=1;IRQ_IN;if(IRQ_I==0){sta=SPI_Read(STATUS);SPI_RW_Reg(WRITE_REG+STATUS,0xff);if(sta&STA_MARK_RX){SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);if (rx_buf[0] == 2){LED01=1;Delay(0xffFff);LED01=0;Delay(0xfFfff);rx_buf[0] = 0;}}else{ifnnrf_CLERN_ALL();ifnnrf_rx_mode();IRQ_OUT;IRQ_O=1;IRQ_IN;Delay(0x0f);while(IRQ_I==0);}}}}@far @interrupt void TIM4_interrupt(void){static unsigned int TIM_Work;static unsigned char TIM_Time;if(But01==0){if(TIM_Work++>2500){// LED01 =~LED01;TIM_Work=0;}}else{TIM_Work =0;// LED01 =0;}TIM4_SR1 = 0x00;return;}stm8_interrupt_vector.c内容/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void @far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};@far @interrupt void NonHandledInterrupt(void){/* in order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */extern @far @interrupt void TIM4_interrupt(void);struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, TIM4_interrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};stm8l10x_diy_port.c内容#include "stm8l10x_diy_port.h"#include "STM8L101F3P.h"#include "stm8l10x_gpio.h"/************************************************************** 功能:配置IO口配置IO输入输出说明输出:配置PC_DDR,PC_CR1寄存器,把相应位拉高即可输入:只配置PD_CR1寄存器,拉高即可/*************************************************************/ void gpio_init(void){GPIO_DeInit(GPIOB);//恢复寄存器到默认值GPIO_DeInit(GPIOC);GPIO_DeInit(GPIOD);/*配置输出****************************************************/ PC_DDR|= 0x04;//LEDPC_CR1|= 0x04;//LEDPD_DDR|= 0x01;//LEDPD_CR1|= 0x01;//LEDPC_DDR|= 0x01;//CEPC_CR1|= 0x01;//CEPB_DDR|= 0x10;//CSNPB_CR1|= 0x10;//CSNPB_DDR|= 0x20;//SCKPB_CR1|= 0x20;//SCKPB_DDR|= 0x80;//MISOPB_CR1|= 0x80;//MISO/*配置输入****************************************************/ PC_CR1|= 0x08;//buttomPB_CR1|= 0x01;//buttomPB_CR1|= 0x40;//mOSIPB_CR1|= 0x02;//IRQLED01=1;LED02=1;IRQ_OUT;//IRQ作为输出IRQ_O=1;CE=0; // chip enableCSN=1; // Spi disableSCK=0; // Spi clock line init high}/************************************************************** 功能:配置时钟/*************************************************************/ void clk_init(void){CLK_CKDIVR = 0x00;CLK_PCKENR|= 0x04;//开启定时器4中断(必修有)/*TIM2:0x01TIM3:0x02TIM4:0x04************************************************************/}/************************************************************** 延迟函数/*************************************************************/ void Delay(unsigned int nCount){while (nCount != 0){nCount--;}}/************************************************************** 按键防抖动及按键锁/*************************************************************/ char Key_Scanf(char Buttom){static char Key_Lock;char ButtomStatus;ButtomStatus=But_OFF ;if(Buttom==But_ON){Delay(0x3ff);/* 消抖*/if((Buttom==But_ON)&&(Key_Lock==1)){ButtomStatus=But_ON;}}else Key_Lock= 1;return ButtomStatus;}stm8l10x_diy_port.h内容#ifndef __stm8l10x_diy_port_H#define __stm8l10x_diy_port_H#include "STM8L101F3P.h"#define L 0#define H 1#define But_ON 0 //按下时为低#define But_OFF 1#define IRQ_OUT PB_DDR|= 0x02 //配置输出#define IRQ_IN PB_DDR&= 0xFD //配置输入_Bool IRQ_O @PB_ODR:1;//IRQ输出。

STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码

STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码

STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码STC 51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码原文:(改自周立功软件包)#include <reg51.h>#include <intrins.h>#define uchar unsigned char /*宏定义*/#define uint unsigned intextern void Delay1us(unsigned char );sbit SDA=P1^6; /*模拟I2C数据传送位*/sbit SCL=P1^7; /*模拟I2C时钟控制位*/bit ack; /*应答标志位*//************************************************************** *****起动总线函数函数原型: void Start_I2c();功能: 启动I2C总线,即发送I2C起始条件.*************************************************************** *****/void Start_I2c(){SDA=1; /*发送起始条件的数据信号*/Delay1us(1);SCL=1;Delay1us(5); /*起始条件建立时间大于4.7us,延时*/SDA=0; /*发送起始信号*/Delay1us(5); /* 起始条件锁定时间大于4μs*/SCL=0; /*钳住I2C总线,准备发送或接收数据 */Delay1us(2);}/************************************************************** *****结束总线函数函数原型: void Stop_I2c();功能: 结束I2C总线,即发送I2C结束条件.*************************************************************** *****/void Stop_I2c(){SDA=0; /*发送结束条件的数据信号*/Delay1us(1); /*发送结束条件的时钟信号*/SCL=1; /*结束条件建立时间大于4us*/Delay1us(5);SDA=1; /*发送I2C总线结束信号*/Delay1us(4);}/*******************************************************************字节数据发送函数函数原型: void SendByte(uchar c);功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0)发送数据正常,ack=1; ack=0表示被控器无应答或损坏。

51单片机串口变并口汇编程序

51单片机串口变并口汇编程序

51单片机串口变并口汇编程序一、背景介绍单片机是一种集成了处理器、存储器和输入输出接口的微型计算机系统,广泛应用于各种电子设备中。

其中,51单片机是一种非常常见且功能强大的单片机型号。

而串口和并口是单片机与外部设备进行数据传输的两种常见方式。

本文将探讨如何使用汇编语言编写一个将串口转换为并口的51单片机程序。

二、串口与并口的概念1. 串口串口是指利用一对数据线进行数据传输的通信接口。

串口通信可以实现双向数据传输,常用于计算机与外部设备之间的数据交换。

串口通信的优势在于能够以较低的成本实现较长距离的数据传输,且占用的引脚较少。

2. 并口并口是指利用多条数据线进行数据传输的通信接口。

并口通信一般只能实现单向数据传输,常用于单片机与外围设备之间的数据交换。

并口通信的优势在于能够以较高的速度进行数据传输,但由于占用的引脚较多,因此在设计中需要考虑引脚的分配和接口电路的设计。

三、串口变并口的原理串口与并口的数据传输方式和电气特性不同,因此需要一定的电路转换才能实现串口变并口。

常见的串口变并口电路采用的是移位寄存器,通过串行-并行转换实现数据的传输。

串口变并口的原理如下:1.串口接收到的数据通过串行-并行转换电路和移位寄存器转换为并行数据。

2.并口的数据通过并行-串行转换电路和移位寄存器转换为串行数据,然后通过串口发送出去。

四、51单片机串口变并口汇编程序实现步骤以下是使用51单片机汇编语言编写的串口变并口程序的实现步骤:1.初始化串口:设置串口的波特率、数据位数、停止位、校验位等参数。

2.初始化并口:设置并口的工作模式、数据线的方向等参数。

3.循环接收串口数据:使用串口中断,将接收到的串口数据存储到缓冲区中。

4.将串口数据转换为并口数据:通过移位寄存器和并口接口电路将串口数据转换为并口数据。

5.将并口数据发送出去:将转换后的并口数据通过并口接口电路发送给外部设备。

6.跳转回循环接收串口数据的步骤,完成循环。

51单片机模拟串口的三种方法

51单片机模拟串口的三种方法

51单片机模拟串口的三种方法51单片机模拟串口的三种方法随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。

这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51系列只提供一个串口,那么另一个串口只能靠程序模拟。

本文所说的模拟串口,就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况置1或置0。

至于串口通信的波特率,说到底只是每位电平持续的时间,波特率越高,持续的时间越短。

如波特率为9600BPS,即每一位传送时间为1000ms/9600=0.104ms,即位与位之间的延时为为0.104毫秒。

单片机的延时是通过执行若干条指令来达到目的的,因为每条指令为1-3个指令周期,可即是通过若干个指令周期来进行延时的,单片机常用11.0592M的的晶振,现在我要告诉你这个奇怪数字的来历。

用此频率则每个指令周期的时间为(12/11.0592)us,那么波特率为9600BPS每位要间融多少个指令周期呢?指令周期s=(1000000/9600)/(12/11.0592)=96,刚好为一整数,如果为4800BP S则为96x2=192,如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。

至于别的晶振频率大家自已去算吧。

现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。

方法一:延时法通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。

#define uchar unsigned charsbit P1_0 = 0x90;sbit P1_1 = 0x91;sbit P1_2 = 0x92;#define RXD P1_0#define TXD P1_1#define WRDYN 44 //写延时#define RDDYN 43 //读延时//往串口写一个字节void WByte(uchar input){uchar i=8;TXD=(bit)0; //发送启始位Delay2cp(39);//发送8位数据位while(i--){TXD=(bit)(input&0x01); //先传低位Delay2cp(36);input=input>>1;}//发送校验位(无)TXD=(bit)1; //发送结束位Delay2cp(46);}//从串口读一个字节uchar RByte(void){uchar Output=0;uchar i=8;uchar temp=RDDYN;//发送8位数据位Delay2cp(RDDYN*1.5); //此处注意,等过起始位 while(i--){Output >>=1;if(RXD) Output |=0x80; //先收低位Delay2cp(35); //(96-26)/2,循环共占用26个指令周期}while(--temp) //在指定的时间内搜寻结束位。

C8051F系列单片机串口通讯程序

C8051F系列单片机串口通讯程序

C8051F系列单片机串口通讯程序C8051F系列单片机串口通讯程序采用C8051F020单片机//串口编程--接收PC发过来的字符串,回发字符串.发送期间中断控制LED灯闪烁//采用外部晶振22.1184MHz 使用定时器1,方式2产生波特率,SMOD = 0或者 1 //定时器初值X=256-SYSCLK*(SMOD+1)/(BAUDRATE*384)/#includesfr16 TMR3RL = 0x92; //定时器3重装载寄存器sfr16 TMR3 = 0x94; //定时器3计数器#define uchar unsigned char#define uint unsigned int//----------------------------------------------------------------------//参数设置区//----------------------------------------------------------------------#define BAUDRATE 4800 //波特率bps#define CLKOUT 22118400 //外部晶振,修改也要修改OSCXCN #define SMODVAL 0 //SMOD的值,修改请也修改PCONVAL#define PCONVAL 0x00 //PCON的值,=0x00时SMOD0=0; =0x80时SMOD0=1 #define TXVAL (256-CLKOUT*(SMODVAL+1)/BAUDRATE/384) //定时器初值#define MAX_LEN 10 //每次接收/发送字符串的长度//---------------------------------------------------------------------//全局变量//---------------------------------------------------------------------sbit LED = P1^6; //LED '1'亮'0'灭bit readFlag = 0; //读标志uchar readCounts = 0; //已经读取的字符个数,与MAX_LEN比较uchar idata trdata[MAX_LEN]; //要接收/发送的字符串//----------------------------------------------------------------------//子函数声明//---------------------------------------------------------------------- void SYSCLK_Init(void); //系统时钟初始化void PORT_Init(void); //端口初始化void UART0_Init(void); //串口UART0初始化void Send_Char(uchar ch); //发送单个字符void Send_String(uchar * str, uint len); //发送一个字符串void UART0_ISR(); //串口中断服务程序,接收字符void Timer3_Init(uint counts); //定时器3初始化void Timer3_ISR(void); //定时器3中断服务程序//---------------------------------------------------------------------- //主函数//---------------------------------------------------------------------- void main(void){WDTCN = 0xde; //禁止看门狗WDTCN = 0xad;SYSCLK_Init(); //时钟初始化PORT_Init(); //端口初始化UART0_Init(); //串口初始化Timer3_Init(CLKOUT/12/10); //定时器初始化EA = 1; //开全局中断while(1){if(readFlag) //已经读取{readFlag = 0; //清零Send_String(trdata,MAX_LEN); //发送字符串}}}//----------------------------------------------------------------------//子函数具体实现//----------------------------------------------------------------------//系统时钟初始化void SYSCLK_Init(void){uint i;OSCXCN = 0x67; //采用外部晶振22.1184MHz,不分频. 选型OSCXCN=0110,0111 for(i=0;i<256;i++); //等待>1mswhile(!(OSCXCN&0x80)); //查询直到XTLVLD=1,晶振稳定OSCICN = 0x88; //切换到外部振荡器,允许时钟失效监测器. OSCICN=1000,1000 }//端口初始化void PORT_Init(void){XBR0 = 0x04; //允许UART0,RX,TX连到2个端口引脚. XBR0=0000,0100XBR1 = 0x00;XBR2 = 0x40; //交*开关使能P0MDOUT |= 0x03; //P0.0为推拉方式输出,即TX0,RX0所在的端口0000,0011P1MDOUT |=0x40; //P1.6为推拉方式输出,即LED所在的端口0100,0000}//串口初始化void UART0_Init(void){SCON0 = 0x50; //选择串口方式1,波特率可变SCON0=0101,0000TMOD = 0x20; //选择T1,方式2,自动再装入8位计数器TH1 = (int)TXVAL; //T1初值,根据波特率,时钟等计算. 0xF4, bps=4800bpsTL1 = (int)TXVAL;ES0 = 1; //UART0中断开启TR1 = 1; //启动定时器T1PCON |= PCONVAL; //PCON=0x00,SMOD = 0 ; PCON=0x80,SMOD=1 TI0 = 1; //声明TX0就绪,可以发送TR0 = 1;}//定时器初始化void Timer3_Init(uint counts){TMR3CN = 0x00; //禁止定时器T3,清TF3,采用SYSCLK/12为时基TMR3RL = -counts; //初始化重装载值TMR3 = 0xffff; //设置为立即重装载EIE2 |= 0x01; //T3中断开启TMR3CN |= 0x04; //启动T3}//发送单个字符void Send_Char(uchar ch){SBUF0 = ch; //送入缓冲区while(TI0 == 0); //等待发送完毕TI0 = 0; //软件清零}//发送字符串,调用Send_Char() len字符串长度void Send_String(uchar * str,uint len){uint k = 0;do{Send_Char(*(str + k));k++;} while(k < len);}//定时器3中断服务程序void Timer3_ISR(void) interrupt 14 using 0 {TMR3CN &= ~(0x80); //清TF3LED = ~LED;}//UART0中断服务程序. 接收字符void UART0_ISR(void) interrupt 4 using 1 {uchar rxch;if(RI0) //中断标志RI0=1 数据完整接收{RI0 = 0; //软件清零rxch = SBUF0; //读缓冲if(readCounts>=MAX_LEN){readCounts = 0;readFlag = 1;}trdata[readCounts] = rxch; //存入数组,供发送readCounts++;}}//------------------------------------------------------------- //程序结束。

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)#include#include "UART1.h"#include "commdriver.h"//当前适用于C51//可以根据具体CPU型号,修改宏定义和串口初始化代码就可以#define CPU_XTAL 22118400 //CPU频率#define FUNCTION_NULL 0 //没有定义函数#define COM_TI TI //发送中断寄存器#define COM_TI0() {TI = 0;} //发送中断寄存器清零#define COM_TI1() {TI = 1;} //发送中断寄存器置一( 强行置一触发发送中断)#define COM_TI_SBUF(dat) {SBUF = dat;} //发送数据到硬件缓冲区#define COM_TI_End() {return;} //发送结束处理函数#define COM_RI RI //接收中断寄存器#define COM_RI0() {RI = 0;} //接收中断寄存器清零#define COM_RI1() {RI = 1;} //接收中断寄存器置一#define COM_RI_SBUF(dat) {dat = SBUF;} //提取接收硬件缓冲区数据#define COM_TI_FLAG COM_TI //发送中断标志寄存器(非中断发送方式使用)#define COM_TI_FLAG0() COM_TI0() //发送中断标志寄存器清零(非中断发送方式使用)void (*COM1RevEvent)(unsigned char dat); //数据接收事件#define LenTxBuf 30 //发送缓冲区长度#define LenRxBuf 1 //接收缓冲区长度volatile unsigned char TxBuf1[LenTxBuf],RxBuf1[LenRxBuf]; //收发缓冲区实体volatile unsigned char *inTxBuf1,*outTxBuf1,*inRxBuf1,*outRxBuf1; //收发缓冲区读写指针volatile unsigned char TIflag1=1;//Note:It must be 1. //发送缓冲区为空标志//*********************#define _TxBuf TxBuf1#define _RxBuf RxBuf1#define _inTxBuf inTxBuf1#define _outTxBuf outTxBuf1#define _inRxBuf inRxBuf1#define _outRxBuf outRxBuf1#define _TIflag TIflag1/*************函数声明****************/#define _COMRevEvent COM1RevEvent //串口接收事件#define _USART_IRQ void USART1_IRQHandler(void) interrupt 4 //串口中断服务程序#define _COM_Buffer_Init void COM1_Buffer_Init(void) //串口缓冲区初始化#define _COM_Open void COM1_Open(unsigned int baudrate,void (*revevent)(unsigned char dat)) // 串口初始化#define _COM_Close void COM1_Close(void) //关闭串口#define _COM_GetOneByte unsigned charCOM1_GetOneByte(unsigned char *ch) //获取一个字节#define _COM_GetPChar unsigned char COM1_GetPChar(unsigned char *ch,unsigned char len) //获取指定长度字节数组#define _COM_RxByte unsigned char COM1_RxByte(void) //获取接收字节个数//********缓冲区中断方式发送(安全性高)#define _COM_SendOneByte unsigned char COM1_SendOneByte(unsigned char one_byte) // 发送一个字节#define _COM_SendPChar void COM1_SendPChar(unsigned char *P,unsigned char Len) //发送定长字节数组#define _COM_SendString void COM1_SendString(unsigned char *P) //发送字符串//********非缓冲区中断方式发送#define _COM_PrintOneByte void COM1_PrintOneByte(unsigned char c) // 发送一个字节#define _COM_PrintPChar void COM1_PrintPChar(unsigned char *buf,unsigned int len) //发送定长字节数组#define _COM_PrintString void COM1_PrintString(unsigned char *P) //发送字符串//*************内部引用模型函数(外部不关心,移植时修改后面函数名,要与上面对应的外部声明的函数名一致)*******************#define COM_GetOneByte_(ptr) COM1_GetOneByte(ptr) //与上面获取一个字节的函数对应#define COM_SendOneByte_(dat) COM1_SendOneByte(dat) //与上面发送一个字节的函数对应#define COM_PrintOneByte_(dat) COM1_PrintOneByte(dat) //与上面发送一个字节的函数对应//*********************函数模型定义区(不需要修改)*****************/****************************函数模型:void USART_IRQHandler(void)函数功能:串口中断服务程序入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_USART_IRQ //串口1中断{volatile unsigned char *t;if(COM_RI){COM_RI0(); //清接收标记if(_COMRevEvent != FUNCTION_NULL) //自定义接收事件{COM_RI_SBUF(*_inRxBuf);_COMRevEvent(*_inRxBuf);}else{t = _inRxBuf;t++;if(t == (_RxBuf + LenRxBuf)) t = _RxBuf;if(t != _outRxBuf) //RxBuf No Full{COM_RI_SBUF(*_inRxBuf);_inRxBuf = t;}}}if(COM_TI){COM_TI0();if(_inTxBuf == _outTxBuf) {_TIflag = 1;COM_TI_End();};//TxBuf1 EmptyCOM_TI_SBUF(*_outTxBuf); _outTxBuf++;if(_outTxBuf == (_TxBuf+LenTxBuf)) _outTxBuf = _TxBuf;}}/****************************函数模型:void COM1_Buffer_Init(void)函数功能:串口1缓冲区初始化入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Buffer_Init{_inTxBuf = _TxBuf;_outTxBuf = _TxBuf;_inRxBuf = _RxBuf;_outRxBuf = _RxBuf;}/****************************函数模型:void COM_Open(unsigned int baudrate,void (*revevent)(unsigned char dat))函数功能:系统串口初始化入口参数: unsigned int baudrate:串口波特率返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Open{//定时器1做波特率发生器TI = 0; /* clear transmit interrupt */TR1 = 0; /* stop timer 1 */ET1 = 0; /* disable timer 1 interrupt */PCON |= 0x80; /* 0x80=SMOD: set serial baudrate doubler */ TMOD &= ~0xF0; /* clear timer 1 mode bits */TMOD |= 0x20; /* put timer 1 into MODE 2 */TH1 = (unsigned char) (256 - (CPU_XTAL / (16L * 12L * baudrate)));TR1 = 1; /* start timer 1 *///设置串口1模式SM0 = 0; SM1 = 1; /* serial port MODE 1 */SM2 = 0;REN = 1; /* enable serial receiver */RI = 0; /* clear receiver interrupt */TI = 0; /* clear transmit interrupt */ES = 1; /* enable serial interrupts */PS = 1; /* set serial interrupts to low priority */_COMRevEvent = revevent;}/****************************函数模型:void COM1_Close(void)函数功能:关闭系统串口入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Close{}/****************************函数模型:unsigned char COM1_GetOneByte(unsigned char *ch)函数功能:获取一个字节入口参数:unsigned char *ch:接收字节指针返回值: unsigned char *ch:接收字节指针unsigned char :获取状态;0:成功,1:失败(缓冲区为空)修改者:修改时间:修改内容简要:***************************/_COM_GetOneByte{if(_inRxBuf == _outRxBuf) {return 0;}; //RxBuf Empty*ch = *_outRxBuf; _outRxBuf++;if(_outRxBuf==_RxBuf+LenRxBuf) _outRxBuf = _RxBuf;return 1;}/****************************函数模型:unsigned char COM_GetPChar(unsigned char *ch,unsigned char len)函数功能:获取指定长度字节数组入口参数: unsigned char *ch:接收字节数组指针unsigned char len:接收字节个数返回值: unsigned char *ch:接收字节数组指针unsigned char:实际接收字节个数修改者:修改时间:修改内容简要:***************************/_COM_GetPChar{unsigned char i = 0;do{len--;if(!COM_GetOneByte_(ch)) break;i++;ch++;}while(len);return i;}/****************************函数模型:unsigned char COM_RxByte(void)函数功能:获取接收缓冲区有效字节个数入口参数:无返回值: unsigned char:接收缓冲区有效字节个数修改者:修改时间:修改内容简要:***************************/_COM_RxByte{if(_inRxBuf>=_outRxBuf) return (_inRxBuf-_outRxBuf);else return LenRxBuf-(_outRxBuf-_inRxBuf);}/****************************函数模型:unsigned char COM_SendOneByte(unsigned char one_byte)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:unsigned char:发送状态,0:成功,1:失败(缓冲区满)修改者:修改时间:修改内容简要:***************************/_COM_SendOneByte{volatile unsigned char *t;if(_TIflag){_TIflag = 0;COM_TI1();}t = _inTxBuf;t++;if(t == _TxBuf + LenTxBuf) t = _TxBuf;if(t == _outTxBuf) {return 1;};//TxBuf Full*_inTxBuf = one_byte;_inTxBuf = t;return 0;}/****************************函数模型:void COM_SendPChar(unsigned char *P,unsigned char Len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendPChar{while(Len){//while(COM1_SendOneByte(*P)); //发送失败,继续发送,知道发送成功COM_SendOneByte_(*P);P++;Len--;}}/****************************函数模型:void COM_SendString(unsigned char *P)函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendString{while(*P){COM_SendOneByte_(*P);P++;}}//**************** 非缓冲区中断方式发送/****************************函数模型:void COM_PrintOneByte(unsigned char c)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintOneByte{COM_TI_FLAG0();COM_TI_SBUF(c); //发送数据while(!COM_TI_FLAG) ; //等待发送结束}/****************************函数模型:void COM_PrintPChar(unsigned char *buf,unsigned int len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintPChar{while(len){COM_PrintOneByte_(*buf);buf ++;len--;}}/****************************函数模型:void COM_PrintString(unsigned char *P) 函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintString{while(*P){COM_PrintOneByte_(*P);P++;}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void _putchar( char ch ) { while ( flag_tx_ready ); user_tx_buffer = ch;
// invoke_UART_transmit timer_tx_ctr = 3; bits_left_in_tx = tx_num_of_bits; internal_tx_buffer = (user_tx_buffer<<1) | 0x200; flag_tx_ready = TRUE; }
3 欢迎光临中国最大的电子工程师应用网站 网址:
电子下载站 资料版权归合法所有者所有 严禁用于商业用途
// Test for Start Bit if ( start_bit==0 ) { flag_rx_ready = TRUE; internal_rx_buffer = 0; timer_rx_ctr = 4; bits_left_in_rx = rx_num_of_bits; rx_mask = 1; } } else // rx_busy { if ( --timer_rx_ctr<=0 ) { // rcv timer_rx_ctr = 3; flag_in = get_rx_pin_status(); if ( flag_in ) {
char _getchar( void ) { char ch;
do { while ( qout==qin ) { idle(); } ch = inbuf[qout] & 0xFF; if ( ++qout>=IN_BUF_SIZE ) { qout = 0; } } while ( ch==0x0A || ch==0xC2 ); return( ch ); }
static char flag_rx_waiting_for_stop_bit; static char flag_rx_off; static char rx_mask; static char flag_rx_ready; static char flag_tx_ready; static char timer_rx_ctr; static char timer_tx_ctr; static char bits_left_in_rx; static char bits_left_in_tx; static char rx_num_of_bits; static char tx_num_of_bits; static char internal_rx_buffer; static char internal_tx_buffer; static char user_tx_buffer;
欢迎光临中国最大的电子工程师应用网站 网址:
电子下载站 资料版权归合法所有者所有 严禁用于商业用途
// Turns on the receive function. // 5. void turn_rx_off( void ) // Turns off the receive function. // 6. void putchar( char ) // Writes a character to the serial port.
电子下载站 资料版权归合法所有者所有 严禁用于商业用途
发一个通用的 I/O 模拟串口程序(适用于任何带有定时器的单片机)
// UART.C // // Generic software uart written in C, requiring a timer set to 3 times // the baud rate, and two software read/write pins for the receive and // transmit functions. // // * Received characters are buffered // * putchar(), getchar(), kbhit() and flush_input_buffer() are available // * There is a facility for background processing while waiting for input // // Colin Gittins, Software Engineer, Halliburton Energy Services // // The baud rate can be configured by changing the BAUD_RATE macro as // follows: // // #define BAUD_RATE 19200.0 // // The function init_uart() must be called before any comms can take place // // Interface routines required: // 1. get_rx_pin_status() // Returns 0 or 1 dependent on whether the receive pin is high or low. // 2. set_tx_pin_high() // Sets the transmit pin to the high state. // 3. set_tx_pin_low() // Sets the transmit pin to the low state. // 4. idle() // Background functions to execute while waiting for input. // 5. timer_set( BAUD_RATE ) // Sets the timer to 3 times the baud rate. // 6. set_timer_interrupt( timer_isr ) // Enables the timer interrupt. // // Functions provided: // 1. void flush_input_buffer( void ) // Clears the contents of the input buffer. // 2. char kbhit( void ) // Tests whether an input character has been received. // 3. char getchar( void ) // Reads a character from the input buffer, waiting if necessary. // 4. void turn_rx_on( void )
void flush_input_buffer( void ) {
5 欢迎光临中国最大的电子工程师应用网站 网址:
电子下载站 资料版权归合法所有者所有 严禁用于商业用途
qin = 0; qout = 0; } char kbhit( void ) { return( qin!=qout ); } void turn_rx_on( void ) { flag_rx_off = FALSE; } void turn_rx_off( void ) { flag_rx_off = TRUE; }
#include <stdio.h>
#define BAUD_RATE 19200.0
#define IN_BUF_SIZE 256
#define TRUE 1 #define FALSE 0
static unsigned char inbuf[IN_BUF_SIZE]; static unsigned char qin = 0; static unsigned char qout = 0;
4 欢迎光临中国最大的电子工程师应用网 网址:电子下载站 资料版权归合法所有者所有 严禁用于商业用途
rx_num_of_bits = 10; tx_num_of_bits = 10;
set_tx_pin_low();
timer_set( BAUD_RATE ); set_timer_interrupt( timer_isr ); // Enable timer interrupt }
void timer_isr(void) { char mask, start_bit, flag_in;
// Transmitter Section if ( flag_tx_ready ) { if ( --timer_tx_ctr<=0 ) {
2 欢迎光临中国最大的电子工程师应用网站 网址:
电子下载站 资料版权归合法所有者所有 严禁用于商业用途
mask = internal_tx_buffer&1; internal_tx_buffer >>= 1; if ( mask ) { set_tx_pin_high(); } else { set_tx_pin_low(); } timer_tx_ctr = 3; if ( --bits_left_in_tx<=0 ) { flag_tx_ready = FALSE; } } } // Receiver Section if ( flag_rx_off==FALSE ) { if ( flag_rx_waiting_for_stop_bit ) { if ( --timer_rx_ctr<=0 ) { flag_rx_waiting_for_stop_bit = FALSE; flag_rx_ready = FALSE; internal_rx_buffer &= 0xFF; if ( internal_rx_buffer!=0xC2 ) { inbuf[qin] = internal_rx_buffer; if ( ++qin>=IN_BUF_SIZE ) { qin = 0; } } } } else // rx_test_busy { if ( flag_rx_ready==FALSE ) { start_bit = get_rx_pin_status();
相关文档
最新文档