51单片机串口接收数据演示源程序
Keil C51串口收发范例及说明
51 //需要在"Uart1.c"文件中修改串口工作参数的函数示范
52 void Uart1_Setup()
53 {
54 unsigned char U1Brt; //波特率重装值数组的指针
55 //串口参数设置--------------------------------------
56 U1Brt=6;
98
参数 2:计数器选择,0,定时器 1;1,独立波特率
99 **********************************************************/
100 void Uart1_Setup()
101 {
102 unsigned char U1Brt; //波特率重装值数组的指针
//收发模式,0 做字符数组处理,遇停止符停止,1 做最大 Uart1_MaxString 位循环写入
80
unsigned char
Read:1;
//接受字符组可读标记
81
unsigned char
Parity:1;
//接收到的奇偶校验状态 1,0
82 }xdata Uart1;
//结构变量名
83
84 //Uart1 包含函数申明---------------------------------
//1 做环回接收处理,0 做字符数组处理
59 Uart1.Read=0;
//清可读标记,并非必要
60 //AUXR |= 0x01;
//串口 1 时基源选择独立波特率发生器
61 AUXR &= 0xFE;
//串口 1 时基源选择定时器 1 做波特率发生器
62 ......
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();
原创:51单片机串口通信(字符串接收和发送)
原创:51单⽚机串⼝通信(字符串接收和发送)下⾯的⽰例代码基于51单⽚机,⽤于快速⼆次开发实现基于串⼝字符串通信控制程序(⽐如要实现电脑控制单⽚机的开灯和关灯),⽰例很⾔简意赅,并附上了详尽的注释,本⽰例代码经过了更新,新版本代码更加友好了,1 #include<reg52.h>23//------------------串⼝通信的数据包协议-----------------//4/*5此程序的串⼝字符串通信使⽤到下⾯的⼀个⾃定义协议,每次通信都是发送或接收⼀个数据包,数据包格式解释如下(长度恒为15):6例如:A01_fmq_01Off___#7 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)8 01-----设备代号9 fmq_01Off___--------指令(长度恒为10),指令的前4个⼈字符是指令头部,指令的后6个字符是指令尾部10 #---------数据包的结束标记1112例如:A02_SenT010250#13 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)14 02-----设备代号15 SenT010250--------指令(长度恒为10),指令的前4个⼈字符是指令头部,指令的后6个字符是指令尾部16 #---------数据包的结束标记17*/18char RecvString_buf[16]; //定义数据包长度为15个字符19#define deviceID_1Bit '0' //⽤于串⼝通信时,定义本地设备ID的第1位20#define deviceID_2Bit '2' //⽤于串⼝通信时,定义本地设备ID的第2位21#define datapackage_headflag 'A' //⽤于串⼝通信时,定义数据包头部的验证标记2223char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','X','X','X','X','X','X','#'}; //这个是曾经⽤来控制温度传感模块(DS18B20)的数据包24char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','X','X','X','X','X','X','#'}; //我随便定义了⼀个数据包⽤来做"⼼跳包",⽐如单⽚机系统向电脑每2秒发送⼀次该数据包,如果电脑没有按时接收到,就认为 25//----------------------------------------------//26/*******************************27串⼝通信28 MCU:89C52RC 11.0592MHz2930//11.0592MHz 0xd0 1200bps31//12MHz 0xcc 1200bps32//11.0592MHz 0xfa 9600bps33//0xf4 11.0592MHz 0xf3 12MHz 4800bps34//均在SMOD=1的情况下(波特率倍增模式)35*******************************/36//串⼝发送函数37void PutString(unsigned char *TXStr)38 {39 ES=0;40while(*TXStr!=0)41 {42 SBUF=*TXStr;43while(TI==0);44 TI=0;45 TXStr++;46 }47 ES=1;48 }49//串⼝接收函数50 bit ReceiveString()51 {52char * RecStr=RecvString_buf;53char num=0;54 unsigned char count=0;55 loop:56 *RecStr=SBUF;57 count=0;58 RI=0;59if(num<14) //数据包长度为15个字符,尝试连续接收15个字符60 {61 num++;62 RecStr++;63while(!RI)64 {65 count++;66if(count>130)return0; //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=13067 }68goto loop;69 }70return1;71 }72//定时器1⽤作波特率发⽣器73void Init_USART()74 {75 SCON=0x50; //串⼝⽅式1,使能接收76 TMOD|=0x20; //定时器1⼯作⽅式2(8位⾃动重装初值)77 TMOD&=~0x10;78 TH1=0xfa; //9600bps79 TL1=0xfa;80 PCON|=0x80; //SMOD=181 TR1=1;82 TI=0;83 RI=0;84//PS=1; //提⾼串⼝中断优先级85 ES=1; //开启串⼝中断使能86 }87//⽐较指令头部88 bit CompareCMD_head(char CMD_head[])89 {90 unsigned char CharNum;91for(CharNum=0;CharNum<4;CharNum++) //指令长度为10个字符92 {93if(!(RecvString_buf[CharNum+4]==CMD_head[CharNum]))94 {95return0; //指令头部匹配失败96 }97 }98return1; //指令头部匹配成功99 }100//⽐较指令尾部(start:从哪⾥开始⽐较,quality:⽐较多少个字符,CMD_tail[]:要⽐较的字符串)101 bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])102 {103 unsigned char CharNum;104for(CharNum=0;CharNum<quality;CharNum++)105 {106if(!(RecvString_buf[start+CharNum]==CMD_tail[CharNum]))107 {108return0;109 }110 }111return1;112 }113 bit Deal_UART_RecData() //处理串⼝接收数据包函数(成功处理数据包则返回1,否则返回0)114 {115//PutString(RecvString_buf);116if(RecvString_buf[0]==datapackage_headflag&&buf_string[14]=='#') //进⾏数据包头尾标记验证117 {118switch(RecvString_buf[1]) //识别发送者设备ID的第1位数字119 {120case'0':121switch(RecvString_buf[2]) //识别发送者设备ID的第2位数字122 {123case'3':124if(CompareCMD_head("Ligt")) //判断指令头部是否为"Ligt"125 {126//下⾯是指令尾部分析127switch(RecvString_buf[8])128 {129case'0':130switch(RecvString_buf[9])131 {132case'0':133134return0;135case'1':136if(CompareCMD_tail(10,3,"Off")) //判断整个数据包是否为:A03_Ligt01Off_#137 {138//如果是则执⾏以下代码139return1;140 }141if(CompareCMD_tail(10,3,"On_")) //判断整个数据包是否为:A03_Ligt01On__#142 {143//如果是则执⾏以下代码144return1;145 }146return0;147default:148return0;149 }150default:151return0;152 }153 }154return0;155156default:157return0;158 }159default:160return0;161 }162 }163return0;164 }165/************************166中断函数167************************/168//串⼝中断服务函数-----------169void USART() interrupt 4//标志位TI和RI需要⼿动复位,TI和RI置位共⽤⼀个中断⼊⼝170 {171if(ReceiveString())172 {173//数据包长度正确则执⾏以下代码174 Deal_UART_RecData();175 }176else177 {178//数据包长度错误则执⾏以下代码179//LED1=~LED1;180 }181 RI=0; //接收并处理⼀次数据后把接收中断标志清除⼀下,拒绝响应在中断接收忙的时候发来的请求182 }183/***************************184主函数185***************************/186void main()187 {188 EA=1; 189 Init_USART(); //初始化串⼝中断通信,当串⼝接受完数据包后,如果检测到数据包包含有效指令,则⾃动执⾏对应的代码,执⾏完⾃动返回到主函数,为了尽可能不影响主函数的时序,串⼝中断函数的执⾏代码不要过复杂190while(1)191 {192//下⾯可以放要经常运⾏的⽤户代码,使⽤PutString()函数来发送数据包,如PutString(HeartBeat); 注:空格的ASCLL码是:0x20,回车是:0x0D193194195 }196 }。
NRF2401在51单片机上的接收与发送程序
//这是在网上收集的程序,版权归原作者所有NRF2401程序(接收部分)jxj2e1v8v 发表于2008-3-31 1:56:00#include <reg52.h>#include<intrins.h>// 常量定义#define uchar unsigned char#define uint unsigned int#define BYTE_BIT0 0x01#define BYTE_BIT1 0x02#define BYTE_BIT2 0x04#define BYTE_BIT3 0x08#define BYTE_BIT4 0x10#define BYTE_BIT5 0x20#define BYTE_BIT6 0x40#define BYTE_BIT7 0x80//---------------------------位变量定义----------------------------------------bdata uchar DATA_BUF; //用于ByteRead和ByteWrite 函数#define DATA7 ((DA TA_BUF&BYTE_BIT7)!=0)#define DATA0 ((DATA_BUF&BYTE_BIT0)!=0)uchar RxBuf[28];// ------------------------------<RF2401_Pins 对应引脚> -----------------------sbit PWR_UP = P1^0;sbit CE = P1^1;// sbit DR2 = P3^2; //暂时没有用到// sbit CLK2 = P1^2;// sbit OUT2 = P1^4;sbit CS = P1^3;sbit DR1 = P3^3;sbit CLK1 = P1^7;sbit DATA = P1^5;//sbit LED0 = P3^4;//sbit LED1 = P3^5;//sbit KEY0 = P3^0;//sbit KEY1 = P3^1;//-------------------------------------------------------------------------------unsigned char TxAddress[4]={0xcc,0xcc,0xcc,0xcc}; //发送地址//---------------------<nRF-Configuration-Register 配置信息>------------------------------//芯片测试用,无需修改#define TEST_2 0x8E // MSB D143-D136#define TEST_1 0x08 // D135~D128#define TEST_0 0x1c // D127~D120// 注意DATAx_W+ADDRx_W+CRC 的值必须小于256!单个数据包的大小必须小于32字节(256位)#define DATA2_W 0x10 //未用到--0x10=2字节//频道2发送/接受数据长度(单位:Bit)#define DATA1_W 0xE0 //28字节16 位//频道1发送/接受数据长度(单位:Bit)//频道2接收地址<-频道2未使用#define ADDR2_4 0x00#define ADDR2_3 0x1c#define ADDR2_2 0xcc#define ADDR2_1 0xcc#define ADDR2_0 0xcc// 频道1接收地址(当前模块地址) <-只是用频道1#define ADDR1_4 0x00#define ADDR1_3 0xcc#define ADDR1_2 0xcc#define ADDR1_1 0xcc#define ADDR1_0 0xcc//接收地址位置设置--CRC设置#define ADDR_W 0x10 //0x10 =2字节//发送/接收地址宽度(单位:Bit)#define CRC_L 0x1 //CRC模式0:8位1:16位#define CRC_EN 0x1 //CRC校验0:禁止1:启用//频道设置--发送方式设置--速率设置--频率设置#define RX2_EN 0x0 //双频道功能0:禁用1:启用#define CM 0x1 //0:Direct Mode 1: Shockburst Mode#define RFDR_SB 0x1 //传输速率0:250k 1: 1M (250k比1M传输距离远)#define XO_F 0x3 //16M D12 D11 D10 确定5种频率#define RF_PWR 0x3 //信号发射功率---0DB//#define RF_CH 0x2 //Channal 频率设置Channel=2400MHz+RF_CH*1.0MHz#define RXEN 0x1 //0:TX 1:RX//<将设置信息组合成每个字节的数据信息#define RFconfig_Bit0 TEST_2#define RFconfig_Bit1 TEST_1#define RFconfig_Bit2 TEST_0#define RFconfig_Bit3 DA TA2_W#define RFconfig_Bit4 DA TA1_W#define RFconfig_Bit5 ADDR2_4#define RFconfig_Bit6 ADDR2_3#define RFconfig_Bit7 ADDR2_2#define RFconfig_Bit8 ADDR2_1#define RFconfig_Bit9 ADDR2_0#define RFconfig_Bit10 ADDR1_4#define RFconfig_Bit11 ADDR1_3#define RFconfig_Bit12 ADDR1_2#define RFconfig_Bit13 ADDR1_1#define RFconfig_Bit14 ADDR1_0#define RFconfig_Bit15 (ADDR_W<<2|CRC_L<<1|CRC_EN)#define RFconfig_Bit16 (RX2_EN<<7|CM<<6|RFDR_SB<<5|XO_F<<2|RF_PWR)#define RFconfig_Bit17 (RF_CH<<1|RXEN)//通过宏定义将18字节的寄存器参数按照各个功能分解,参照DATASHHETuchar code nRF2401_Conf[18]={RFconfig_Bit0,RFconfig_Bit1,RFconfig_Bit2,RFconfig_Bit3,RFconfig_Bit4,RFconfig_Bit5,RFconfig_Bit6,RFconfig_Bit7,RFconfig_Bit8,RFconfig_Bit9, RFconfig_Bit10,RFconfig_Bit11,RFconfig_Bit12,RFconfig_Bit13,RFconfig_Bit14, RFconfig_Bit15,RFconfig_Bit16,RFconfig_Bit17};//------------------------------------------函数申明------------------------------------------void Delay_us(uchar n);void DoClock();void Delay_ms(uchar n);unsigned char Spi_ByteRead(void);void Spi_ByteWrite(unsigned char send);void Config2401(void);void SetTxMode(void);void nRF2401_TxPacket(uchar TxBuf[]);//--------------------------------11.0592M晶振n=100 868us 左右------------------------------- void Delay_us(uchar n){uint i;for(i=0;i<n;i++);}//------------------------------------------ -----------------------------------------void Delay_ms(uchar n){unsigned int i,j,k;for(i=0;i<n;i++){for(k=0;k<5;k++){for(j=0;j<200;j++);}}}//--------------------------SPI读------------------------------------------ unsigned char Spi_ByteRead(void){unsigned char i = 0;for (i=0; i<8; i++){DATA_BUF = DA TA_BUF << 1;CLK1 = 1;DATA = 1; //设置为输入状态if (DATA) //读取最高位,保存至最末尾,通过左移位完成整个字节{DA TA_BUF |= BYTE_BIT0;}else{DA TA_BUF &= ~BYTE_BIT0;}CLK1 = 0;}return DATA_BUF;}//----------------------------------SPI写----------------------------------------- void Spi_ByteWrite(unsigned char send){unsigned char i;DATA_BUF = send;CLK1 = 0;for (i=0; i<8; i++){if (DATA7) //总是发送最高位{DA TA = 1;}else{DA TA = 0;}CLK1 = 1;DATA_BUF = DA TA_BUF << 1;CLK1 = 0;}}//-----------------------------配置2401-------------------------------------------- void Config2401(void){uint i;uchar variable1;PWR_UP=1; //上电CE=0;CS=1; //使RF2401进入配置方式Delay_ms(3); //从上电到进入配置模式需要3ms的延时(最少)for(i=0;i<18;i++) //输入3个测试字节15个配置字节共18Byte{variable1=nRF2401_Conf[i];Spi_ByteWrite(variable1);}CS=0; //Disable CS -----standby modeDATA=0;Delay_us(100);}/*//--------------------------------设置为发送模式----------------------------void SetTxMode(void){//-------------------------------设置为配置模式---------------------------------- PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=0; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}//--------------------------------nRF 数据发送函数-------------------------------- void nRF2401_TxPacket(){int i;uchar variable2;CE=1;for(i=0;i<2;i++) //写入接受地址(按字节对齐){variable2=TxAddress[i];Spi_ByteWrite(variable2);}for(i=0;i<(28);i++) //写入接受地址(按字节对齐){variable2=TxBuf[i];Spi_ByteWrite(variable2);}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}*/void SetRxMode(void){PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=1; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}void nRF2401_RxPacket(){int i;DR1=1;if(DR1==1){for(i=0;i<(28);i++) //写入接受地址(按字节对齐){RxBuf[i]=Spi_ByteRead();}}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}//---------------------------串口初始化----------------------------------void StartUART( void ){ //波特率4800SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;PCON = 0x00;TR1 = 1;}//--------------------------串口接收函数---------------------------------- void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}//------------------------------------主函数--------------------------------------- main(){uchar i;Config2401();Delay_us(100);StartUART();while(1){SetRxMode();nRF2401_RxPacket();for(i=0;i<28;i++){R_S_Byte( RxBuf[i]);}}}NRF2401程序(发送部分)jxj2e1v8v 发表于2008-3-31 1:53:00#include <reg52.h>#include<intrins.h>// 常量定义#define uchar unsigned char#define uint unsigned int#define BYTE_BIT0 0x01#define BYTE_BIT1 0x02#define BYTE_BIT3 0x08#define BYTE_BIT4 0x10#define BYTE_BIT5 0x20#define BYTE_BIT6 0x40#define BYTE_BIT7 0x80//---------------------------位变量定义----------------------------------------bdata uchar DATA_BUF; //用于ByteRead和ByteWrite 函数#define DATA7 ((DA TA_BUF&BYTE_BIT7)!=0)#define DATA0 ((DATA_BUF&BYTE_BIT0)!=0)uchar TxBuf[28]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,};// ------------------------------<RF2401_Pins 对应引脚> -----------------------sbit PWR_UP = P1^0;sbit CE = P1^1;// sbit DR2 = P3^2; //暂时没有用到// sbit CLK2 = P1^2;// sbit OUT2 = P1^4;sbit CS = P1^3;sbit DR1 = P3^3;sbit CLK1 = P1^7;sbit DATA = P1^5;////sbit LED0 = P3^4;//sbit LED1 = P3^5;//sbit KEY0 = P3^0;//sbit KEY1 = P3^1;//-------------------------------------------------------------------------------unsigned char TxAddress[4]={0xcc,0xcc,0xcc,0xcc}; //发送地址//---------------------<nRF-Configuration-Register 配置信息>------------------------------//芯片测试用,无需修改#define TEST_2 0x8E // MSB D143-D136#define TEST_1 0x08 // D135~D128#define TEST_0 0x1c // D127~D120// 注意DATAx_W+ADDRx_W+CRC 的值必须小于256!单个数据包的大小必须小于32字节(256位)#define DATA2_W 0x10 //未用到--0x10=2字节//频道2发送/接受数据长度(单位:Bit)#define DATA1_W 0xE0 //28字节16 位//频道1发送/接受数据长度(单位:Bit)//频道2接收地址<-频道2未使用#define ADDR2_4 0x00#define ADDR2_2 0xcc#define ADDR2_1 0xcc#define ADDR2_0 0xcc// 频道1接收地址(当前模块地址) <-只是用频道1#define ADDR1_4 0x00#define ADDR1_3 0xcc#define ADDR1_2 0xcc#define ADDR1_1 0xcc#define ADDR1_0 0xcc//接收地址位置设置--CRC设置#define ADDR_W 0x10 //0x10 =2字节//发送/接收地址宽度(单位:Bit)#define CRC_L 0x1 //CRC模式0:8位1:16位#define CRC_EN 0x1 //CRC校验0:禁止1:启用//频道设置--发送方式设置--速率设置--频率设置#define RX2_EN 0x0 //双频道功能0:禁用1:启用#define CM 0x1 //0:Direct Mode 1: Shockburst Mode#define RFDR_SB 0x1 //传输速率0:250k 1: 1M (250k比1M传输距离远) #define XO_F 0x3 //16M D12 D11 D10 确定5种频率#define RF_PWR 0x3 //信号发射功率---0DB//#define RF_CH 0x2 //Channal 频率设置Channel=2400MHz+RF_CH*1.0MHz#define RXEN 0x0 //0:TX 1:RX//<将设置信息组合成每个字节的数据信息#define RFconfig_Bit0 TEST_2#define RFconfig_Bit1 TEST_1#define RFconfig_Bit2 TEST_0#define RFconfig_Bit3 DA TA2_W#define RFconfig_Bit4 DA TA1_W#define RFconfig_Bit5 ADDR2_4#define RFconfig_Bit6 ADDR2_3#define RFconfig_Bit7 ADDR2_2#define RFconfig_Bit8 ADDR2_1#define RFconfig_Bit9 ADDR2_0#define RFconfig_Bit10 ADDR1_4#define RFconfig_Bit11 ADDR1_3#define RFconfig_Bit12 ADDR1_2#define RFconfig_Bit13 ADDR1_1#define RFconfig_Bit14 ADDR1_0#define RFconfig_Bit15 (ADDR_W<<2|CRC_L<<1|CRC_EN)#define RFconfig_Bit16 (RX2_EN<<7|CM<<6|RFDR_SB<<5|XO_F<<2|RF_PWR)#define RFconfig_Bit17 (RF_CH<<1|RXEN)//通过宏定义将18字节的寄存器参数按照各个功能分解,参照DATASHHET uchar code nRF2401_Conf[18]={RFconfig_Bit0,RFconfig_Bit1,RFconfig_Bit2,RFconfig_Bit3,RFconfig_Bit4,RFconfig_Bit5,RFconfig_Bit6,RFconfig_Bit7,RFconfig_Bit8,RFconfig_Bit9, RFconfig_Bit10,RFconfig_Bit11,RFconfig_Bit12,RFconfig_Bit13,RFconfig_Bit14, RFconfig_Bit15,RFconfig_Bit16,RFconfig_Bit17};//------------------------------------------函数申明------------------------------------------void Delay_us(uchar n);void DoClock();void Delay_ms(uchar n);unsigned char Spi_ByteRead(void);void Spi_ByteWrite(unsigned char send);void Config2401(void);void SetTxMode(void);void nRF2401_TxPacket(uchar TxBuf[]);//--------------------------------11.0592M晶振n=100 868us 左右------------------------------- void Delay_us(uchar n){uint i;for(i=0;i<n;i++);}//------------------------------------------ -----------------------------------------void Delay_ms(uchar n){unsigned int i,j,k;for(i=0;i<n;i++){for(k=0;k<5;k++){for(j=0;j<200;j++);}}}/*//--------------------------SPI读------------------------------------------unsigned char Spi_ByteRead(void){unsigned char i = 0;for (i=0; i<8; i++){DATA_BUF = DA TA_BUF << 1;CLK1 = 1;DATA = 1; //设置为输入状态if (DATA) //读取最高位,保存至最末尾,通过左移位完成整个字节{DA TA_BUF |= BYTE_BIT0;}else{DA TA_BUF &= ~BYTE_BIT0;}CLK1 = 0;}return DATA_BUF;}*///----------------------------------SPI写----------------------------------------- void Spi_ByteWrite(unsigned char send){unsigned char i;DATA_BUF = send;CLK1 = 0;for (i=0; i<8; i++){if (DATA7) //总是发送最高位{DA TA = 1;}else{DA TA = 0;}CLK1 = 1;DATA_BUF = DA TA_BUF << 1;CLK1 = 0;}}//-----------------------------配置2401-------------------------------------------- void Config2401(void){uint i;uchar variable1;PWR_UP=1; //上电CE=0;CS=1; //使RF2401进入配置方式Delay_ms(3); //从上电到进入配置模式需要3ms的延时(最少)for(i=0;i<18;i++) //输入3个测试字节15个配置字节共18Byte{variable1=nRF2401_Conf[i];Spi_ByteWrite(variable1);}CS=0; //Disable CS -----standby modeDATA=0;Delay_us(100);}//--------------------------------设置为发送模式----------------------------void SetTxMode(void){//-------------------------------设置为配置模式---------------------------------- PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=0; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}//--------------------------------nRF 数据发送函数-------------------------------- void nRF2401_TxPacket(){int i;uchar variable2;CE=1;for(i=0;i<2;i++) //写入接受地址(按字节对齐){variable2=TxAddress[i];Spi_ByteWrite(variable2);}for(i=0;i<(28);i++) //写入接受地址(按字节对齐){variable2=TxBuf[i];Spi_ByteWrite(variable2);}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}//------------------------------------主函数--------------------------------------- main(){Config2401();while(1){nRF2401_TxPacket();SetTxMode();}}。
51单片机教程:单片机串行口通信程序设计
51单片机教程:单片机串行口通信程序设计1.串行口方式0应用编程 8051单片机串行口方式0为移位寄存器方式,外接一个串入并出的移位寄存器,就能扩展一个并行口。
单片机串行口通信程序设计硬件连接图例:用8051单片机串行口外接CD4094扩展8位并行输出口,如图所示,8位并行口的各位都接一个发光二极管,要求发光管呈流水灯状态。
串行口方式0的数据传送可采用中断方式,也可采用查询方式,无论哪种方式,都要借助于TI或RI标志。
串行发送时,能靠TI置位(发完一帧数据后)引起中断申请,在中断服务程序中发送下一帧数据,或者通过查询TI的状态,只要TI为0就继续查询,TI为1就结束查询,发送下一帧数据。
在串行接收时,则由RI引起中断或对RI查询来确定何时接收下一帧数据。
无论采用什么方式,在开始通信之前,都要先对控制寄存器SCON进行初始化。
在方式0中将,将00H送SCON就能了。
单片机串行口通信程序设计列子ORG 2000HSTART: MOV SCON,#00H ;置串行口工作方式0MOV A,#80H ;最高位灯先亮CLR P1.0 ;关闭并行输出(避象传输过程中,各LED的暗红现象) OUT0: MOV SBUF,A ;开始串行输出OUT1: JNB TI,OUT1 ;输出完否CLR TI ;完了,清TI标志,以备下次发送SETB P1.0 ;打开并行口输出ACALL DELAY ;延时一段时间RR A ;循环右移CLR P1.0 ;关闭并行输出JMP OUT0 ;循环说明:DELAY延时子程序能用前面我们讲P1口流水灯时用的延时子程序,这里就不给出了。
二、串行口异步通信org 0000HAJMP STARTORG 30HSTART:mov SP,#5fh ;mov TMOD,#20h ;T1: 工作模式2mov PCON,#80h ;SMOD=1mov TH1,#0FDH ;初始化波特率(参见表)mov SCON,#50h ;Standard UART settingsMOV R0,#0AAH ;准备送出的数SETB REN ;允许接收SETB TR1 ;T1开始工作WAIT:MOV A,R0CPL AMOV R0,AMOV SBUF,ALCALL DELAYJBC TI,WAIT1 ;如果TI等于1,则清TI并转WAIT1AJMP WAITWAIT1: JBC RI,READ ;如果RI等于1,则清RI并转READAJMP WAIT1READ:MOV A,SBUF ;将取得的数送P1口MOV P1,ALJMP WAITDELAY: ;延时子程序MOV R7,#0ffHDJNZ R7,$RETEND将程序编译通过,写入芯片,插入实验板,用通读电缆将实验板与主机的串行口相连就能实验了。
51单片机实现串口通信-收发命令
else if(m=='\b')//b 表退格 //下面几句表删锄 {
UART_Putch('\b'); UART_Putch(' '); UART_Putch('\b'); length=length-1; //删了后总长度减一 }
else {
if((length<Maxchar)&&!(UART_Flag)) str[length++]=m; //比如 m 为 open,先传 0 后传 p,length 加一 }
bit UART_Flag=0; uchar length=0; uchar str[Maxchar];
//receive flag //receive data
void Init_SER() //初始化 uart {
TMOD=0X20; //定时器 1 定时器方式 工作模式 2,可自动重载的 8 位计数器常把定
//输出一个字符 //输出一个字符串
#endif
//RS232.C 子程序 #include "reg52.h" #include<string.h> #define uchar unsigned char #define uint unsigned int #define Maxchar 20
code char COMMAND1[]="IFON"; code char COMMAND2[]="IFOFF"; code char COMMAND3[]="WREG"; code char COMMAND4[]="RREG";
else if( strstr(str,COMMAND4) ) UART_Putstring("->RREG get it\r\n");
单片机串口接收数据并显示
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
uchar code dis4[] = {"多发区 "};
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar IRDIS[2];
uchar IRCOM[4];
void delay0(uchar x); //x*0.14MS
void beep();
void dataconv();
void lcd_pos(uchar X,uchar Y); //确定显示位置
/*******************************************************************/
/* */
sbit LCD_RS = P3^5; //寄存器选择输入
sbit LCD_RW = P3^6; //液晶读/写控制
sb LCD_PSB = P3^7; //串/并方式控制
/* 延时函数 */
/* */
/*******************************************************************/
/* */
/*******************************************************************/
void lcd_wdat(uchar dat)
51单片机AD转换和串口收发子程序代码
}
单片机控制串口无线收发的子程序代码
/**************************************
SCON^7——SM0,与SM1一起构成串口通信方式选择;
SCON^6——SM1;
SCON^4——REN,允许接收位,1为允许接收;
D_IN=(bit)(port&0x80); //送控制字
CLOCK=1; //上升沿
delay(1);
Ct;<=1; //控制字左移一位(下一循环送控制字下一位)
SCON^1——TI,发送中断标志位,发送结束后由硬件自动置1,复位需软件;
SCON^0——RI,接收中断标志位,接收结束后由硬件自动置1,复位需软件;
PCON^7——SMOD,波特率增倍位,1为增倍,0为不增倍;
IE^7——EA,中断允许总控制位,1为CPU开放中断,0为屏蔽所有中断请求;
TR1=1; //启动定时器1
ES=0; //禁止串行中断
}
/**************************************
名称:send
功能:发送一个字节
输入参数:待发送的字节
输出参数:无
*************************************/
单片机控制A/D转换子程序代码
/**************************************
名称:read2543
功能:TLC2543驱动模块
输入参数:port通道号
输出参数:ad转换值
*************************************/
51单片机串口程序
}
}
static Uart_ziyuan(void) //根据程序的状态向外发送数据,需要实时的执行
{
static unsigned char time;
if(time != TIME)
{
UARTDATA.txdconl = Uart_dataup(UARTDATA.txdconl);
SBUF = UARTDATA.TxdDada[UARTDATA.txdconl]; //发现有数据变化就发送数据
Hale Waihona Puke else { UARTDATA.txdflag=0;//数据发送完毕
EA = 1;
}
/****************************************************************
函数功能:串行口接收函数
入口参数:使用全局变量传递
出口参数:接收数据使用 RXDATA rxdcon
*****************************************************************/
*****************************************************************/
void Uart_init(void)
{
//串行口初始化
SCON = 0x50; //串行工作方式1,多机通讯模式,允许接受
TB8 = 1;
PCON &= 0x7f; //串口波特率加倍为SMOD=0,关闭串行波特率加倍功能
51单片机串口通讯UART头文件的源代码
bit bdata sendactive; //发送有效标志
/*串行中断服务程序*/
static void com_isr(void) interrupt 4 using 1
{
//----------接收数据---------------
char c;
if(RI) //接收中断置位
{
c=SBUF;//读字符
RI=0;//清接收中端标志
if(istart+ILEN!=iend)
inbuf[iend++&(ILEN-1)]=c; //缓冲区接收数据
}
//------------发送数据------
if(TI)
{
TI=0; //清发送中断标志
if(ostart!=oend)
char idata outbuf[OLEN]; //发送缓冲区存储数组
#define ILEN 8//串行接收缓冲区大小
unsigned char istart; //接受缓冲区起始索引
unsigned char iend; //接收缓冲区结束索引
char idata inbuf[ILEN]; //接收缓冲区存储数组
putbuf(0x0D); //对新行在LF前发送CR
}
while(sendfull);
putbuf(c);
return(c);
}
//替换标准库函数_getkey程序
//getchar和gets函数使用_getkey
char _getkey(void)
{
char c;
while(iend==istart) //判断接收缓冲区起始索引是否等于接收区结束索引
单片机IO口模拟串口程序(发送+接收)
单片机IO口模拟串口程序(发送+接收)前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。
经过若干曲折并参考了一些现有的资料,基本上完成了。
现在将完整的测试程序,以及其中一些需要总结的部分贴出来。
程序硬件平台:11.0592M晶振,STC单片机(兼容51)/************************************** ************************** 在单片机上模拟了一个串口,使用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,0x5 5,0x55,0x55,0x55,0x55,0x55,0x55,0x55 };sbit newTXD = P2^1;//模拟串口的发送端设为P2.1void UartInit(){SCON = 0x50; // SCON: serail mode 1, 8-bit UARTTMOD |= 0x21; // T0工作在方式1,十六位定时PCON |= 0x80; // SMOD=1;TH0 = 0xFE; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHzTL0 = 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.0592MHzTL0=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_0592uchar tmpbuf2[64]={0};//用来作为模拟串口接收数据的缓存struct{uchar recv :6 ;//tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中uchar send :6 ;//tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口}tmpbuf2_point={0,0};sbit newRXD=P3^2 ;//模拟串口的接收端设为P3.2void UartInit(){SCON=0x50 ;// SCON: serail mode 1, 8-bit UARTTMOD|=0x21 ;// TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1,十六位定时PCON|=0x80 ;// SMOD=1;#ifdef F11_0592TH1=0xE8 ;// Baud:2400 fosc=11.0592MHz 2400bps为从串口接收数据的速率TL1=0xE8 ;// 计数器初始值,fosc=11.0592MHz 因为TH1一直往TL1送,所以这个初值的意义不大TH0=0xFF ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHzTL0=0xA0 ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz#endif#ifdef F18_432TH1=0xD8 ;// Baud:2400fosc=18.432MHz 2400bps为从串口接收数据的速率TL1=0xD8 ;// 计数器初始值,fosc=18.432MHz 因为TH1一直往TL1送,所以这个初值的意义不大TH0=0xFF ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHzTL0=0x60 ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz#endifIE|=0x81 ;// 中断允许总控制位EA=1;使能外部中断0TF0=0 ;IT0=1 ;// 设置外部中断0为边沿触发方式TR1=1 ;// 启动TIMER1,用于产生波特率}void WaitTF0(void){while(!TF0);TF0=0 ;#ifdef F11_0592TH0=0xFF ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz #endif#ifdef F18_432TH0=0xFF ;// 定时器重装初值 fosc=18.432MHzTL0=0x60 ;// 定时器重装初值 fosc=18.432MHz#endif}//接收一个字符uchar RByte(){uchar Output=0 ;uchar i=8 ;TR0=1 ;//启动Timer0#ifdef F11_0592TH0=0xFF ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz #endif#ifdef F18_432TH0=0xFF ;// 定时器重装初值fosc=18.432MHzTL0=0x60 ;// 定时器重装初值fosc=18.432MHz#endifTF0=0 ;WaitTF0();//等过起始位//接收8位数据位while(i--){Output>>=1 ;if(newRXD)Output|=0x80 ;//先收低位WaitTF0();//位间延时}TR0=0 ;//停止Timer0return 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 ;//屏蔽外部中断0tmpbuf2[tmpbuf2_point.recv++]=RByte(); //从模拟串口读取数据,存放到tmpbuf2数组中IE0=0 ;//防止外部中断响应2次,防止外部中断函数执行2次EX0=1 ;//打开外部中断0}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~以上是两个独立的测试程序,分别是模拟串口发送的测试程序和接收的测试程序上面两个程序在编写过程中参考了这篇文章《51单片机模拟串口的三种方法》(在后文中简称《51》),但在它的基础上做了一些补充,下面是若干总结的内容:1、《51》在接收数据的程序中,采用的是循环等待的方法来检测起始位(见《51》的“附:51 IO 口模拟串口通讯C源程序(定时器计数法)”部分),这种方法在较大程序中,可能会错过起始位(比如起始位到来的时候程序正好在干别的,而没有处于判断起始位到来的状态),或者一直在检测起始位,而没有办法完成其他工作。
51单片机利用串口接收GPS信号并液晶显示C语言
#include <reg52.h> //89C52单片机头文件#include <LCD_code.h> //液晶LCD的字模文件#include <intrins.h>//功能引脚定义sbit A = P0^7; //数据1/命令0选择sbit RW = P0^6; //读1/写0sbit E1 = P0^4; //片选1(Master)sbit E2 = P0^5; //片选2(slave)sbit LED= P0^3; //背光sbit up = P0^0; //向上翻页键sbit down= P0^1; //向下翻页键#define data P2 //液晶并行数据//液晶显示控制命令表#define disp_on 0xAf //显示关闭#define disp_off 0xAe //显示打开#define disp_start_line 0xC0 //显示起始地址(后5位-表示0-31行)#define page_addr_set 0xB8 //页地址设置(0~3)#define col_addr_set 0x00 //列地址设置(0~61)#define status_busy 0x80 //0=ready#define modeRWite 0xEE //写模式#define dynamic_driver 0xA4 //动态驱动#define adc_select 0xA0 //clockwise#define clk32 0xA9 //刷新时钟设置1/32#define clk16 0xA8 //刷新时钟设置1/16#define reset 0xE2 //软件复位#define uchar unsigned char#define uint unsigned int//全局变量,及标志位定义uchar time_counter = 0; //定时器的软件计数器uchar key = 0; //键盘值uchar serial_counter; //串行计数器bit disp_flag = 0; //显示更新标志uchar bdata serial_byte = 0; //串行口标志位定义字节sbit Sflag = serial_byte^0; //串行接收头部标志,一下8个都定义在'serial_byte'内sbit G1flag = serial_byte^1;sbit Pflag = serial_byte^2;sbit G2flag = serial_byte^3;sbit G3flag = serial_byte^4;sbit Aflag = serial_byte^5;sbit DFflag = serial_byte^6;sbit ENflag = serial_byte^7;bit r_flag = 0;unsigned char idata serial_buff[77]; //串行接收缓冲//uchar code head[] = {'$','G','P','G','G','A',','};//bit serial_flag = 0;////液晶操作主要函数//////////////////////////////////////////////////////////////void lcd_init(void)//引用:lcd_init(); 说明:LCD初始化;//////////////////////////////////////////////////////////////////////////////////void lcd_clr(void)//引用:lcd_clr(); 说明:LCD清屏;////////////////////////////////////////////////////////////////////////////////void lcd_init(void); //LCD初始化void lcd_clr(void); //LCD清屏void wait_ready(void); //等待readyvoid draw_bmp(uchar col,uchar layer,uchar width,uchar *bmp); //点阵码显示输出void ASCII2BCD(void); //ASCII码转换为BCD码void logo(void); //开机画面显示/*----------------------------------------------------------------------------中断程序-----------------------------------------------------------------------------*///////////////////////////////////////////////////////////////////////////////////定时器0中断函数,用于控制背光灯延时10S熄灭///////////////////////////////////////////////////////////////////////////////void int_t0() interrupt 1 using 1{ //定时器0中断函数,用于控制背光灯延时10S熄灭TH0 = 0x4C;TL0 = 0x00; //重装定时器0,定时50mStime_counter ++; //软件计数器+1;if (time_counter == 200) //软件计数器定时到10S,关背光,定时器0,清软件计数器{time_counter = 0;LED = 1;TR0 = 0;}}//////////////////////////////////////////////////////////////////////////////////串行口中断函数,用于语句'$GPGGA'判断和此语句的接收///////////////////////////////////////////////////////////////////////////////void serial() interrupt 4 using 2{uchar pp;RI=0;pp=SBUF;if(ENflag==1) //串口接收完毕,可以用来显示,清标志位重新开始{disp_flag=1;serial_byte = 0;}else if(DFflag==1) //'$GPGGA'头判断完毕,开始接收$GPGGA,语句的数据{if(pp==42)ENflag=1; //等待收到'*'结束接收else{serial_buff[serial_counter]=pp; //没收到'*',继续接收,数据放入串口缓冲serial_counter++;}}else if(Aflag==1) //第六个为'A',判断第七个是不是','{if(pp==44)DFflag=1; //第七个个是','开始接收$GPGGA,语句的数据elseserial_byte = 0; //不是',',清标志位}else if(G3flag==1) //第五个为'G',判断第六个是不是'A'{if(pp==65)Aflag=1; //第六个是'A'判断下一个是不是','elseserial_byte = 0; //不是'A',清标志位}else if(G2flag==1) //第四个为'G',判断第五个是不是'G'{if(pp==71)G3flag=1; //第五个是'G'判断下一个是不是'A'elseserial_byte = 0; //不是'G',清标志位}else if(Pflag==1) //第三个为'P',判断第四个是不是'G'{if(pp==71)G2flag=1; //第四个是'G'判断下一个是不是'G'elseserial_byte = 0; //不是'G',清标志位}else if(G1flag==1) //第二个为'G',判断第三个是不是'P'{if(pp==80)Pflag=1; //第三个是'P'判断下一个是不是'G'elseserial_byte = 0; //不是'P',清标志位}else if(Sflag==1) //第一个为'$',判断第二个是不是'G'{if(pp==71)G1flag=1; //第二个是'G'判断下一个是不是'P' elseserial_byte = 0; //不是'G',清标志位}else if(pp==0x24) //判断第一个是不是${Sflag=1; //第一个为$,判断下一个是不是Gserial_counter=0; //串行计数器清零}}/*void serial() interrupt 4 using 2{uchar i,buff;RI = 0;buff = SBUF;if(serial_flag == 1){serial_buff[serial_counter] = buff;serial_counter ++;if(serial_counter > 37){serial_flag = 0;serial_counter = 0;for(i=0;i>7;i++){if(head[i] == serial_buff[i]){disp_flag = 1;}else{disp_flag = 0;i = 8;}}}}else{if(SBUF == '$'){serial_buff[0] = buff;serial_flag = 1;serial_counter ++;}else{serial_flag = 0;serial_counter = 0;}}}*///////////////////////////////////////////////////////////////////////////////////调用方式:void send_mi(uchar instuction)//函数说明:发指令instruction到主窗口(内函数,私有,用户不能直接调用)////////////////////////////////////////////////////////////////////////////////void send_mi(uchar instruction){E2 = 0; //关SlaverE1 = 1; //开Masterwait_ready(); //判断忙A = 0; //指令RW = 0; //写触发data = instruction; //指令码E1 = 0; //关Master}//////////////////////////////////////////////////////////////////////////////////调用方式:void OutMD(uchar i)//函数说明:发数据data到主窗口(内函数,私有,用户不能直接调用)////////////////////////////////////////////////////////////////////////////////void send_md(uchar c){E2 = 0; //关SlaverE1 = 1; //开Masterwait_ready(); //判断忙A = 1; //数据RW = 0; //写触发data = c; //数据E1 = 0; //关Master}//////////////////////////////////////////////////////////////////////////////////调用方式:void send_si(uchar instruction)//函数说明:发指令instruction到从窗口(内函数,私有,用户不能直接调用) ////////////////////////////////////////////////////////////////////////////////void send_si(uchar instruction){E1 = 0; //关MasterE2 = 1; //开Slaverwait_ready(); //判断忙A = 0; //指令RW = 0; //写触发data=instruction; //指令码E2 = 0; //关Slaver}//////////////////////////////////////////////////////////////////////////////////调用方式:void send_sd(uchar data)//函数说明:发数据data到从窗口(内函数,私有,用户不直接调用)////////////////////////////////////////////////////////////////////////////////void send_sd(uchar c){E1 = 0; //关MasterE2 = 1; //开Slaverwait_ready(); //判断忙A = 1; //数据RW = 0; //写触发data = c; //数据E2 = 0; //关Slaver}//////////////////////////////////////////////////////////////////////////////////等待ready:等待LCD内部操作完成,判忙////////////////////////////////////////////////////////////////////////////////void wait_ready(void){A = 0; //指令RW = 1; //读_nop_(); //空操作,产生汇编里面的nopwhile(data & status_busy); //读入LCD状态,1=忙,一直等待LCD内部操作完成}//////////////////////////////////////////////////////////////////////////////////调用方式:void lcd_init(void)//函数说明:122x32LCD初始化,开机后仅调用一次////////////////////////////////////////////////////////////////////////////////void lcd_init(void){send_mi(reset); //复位m-left,s-rightsend_si(reset);send_mi(disp_off); //关闭显示send_si(disp_off);send_mi(dynamic_driver);//动态驱动send_si(dynamic_driver);send_mi(clk32); //1/32占空比send_si(clk32);send_mi(adc_select); //clockwisesend_si(adc_select);send_mi(modeRWite); //写模式结束send_si(modeRWite);send_mi(col_addr_set); //归回零列,设定显示起始行首send_mi(disp_start_line);send_si(col_addr_set);send_si(disp_start_line);send_mi(disp_on); //开显示send_si(disp_on);}//////////////////////////////////////////////////////////////////////////////// //调用方式:void lcd_clr(void)//函数说明:清屏//////////////////////////////////////////////////////////////////////////////// void lcd_clr(void){uchar i, page;for (page=0;page<4;page++){send_mi(page_addr_set|page);//设置页从0-3send_si(page_addr_set|page);send_mi(0); //主窗口设置为0列send_si(0); //从窗口设置为0列for (i=0;i<62;i++) //全部写入0x00{send_md(0x00);send_sd(0x00);}}}//////////////////////////////////////////////////////////////////////////////// //调用方式:void set_page(uchar page)//函数说明:同时设置主(右)从(左)显示页为0-3页//////////////////////////////////////////////////////////////////////////////// void set_page(uchar page){send_mi(page_addr_set|page);send_si(page_addr_set|page);}//////////////////////////////////////////////////////////////////////////////////调用方式:void SetAddress(uchar address)//函数说明:同时设置主(右)从(左)列地址为0-61列////////////////////////////////////////////////////////////////////////////////void set_address(uchar address){send_mi(address&0x7F); //&0x7F,考虑到防止越限send_si(address&0x7F);}//////////////////////////////////////////////////////////////////////////////////调用方式:void putchar_l(uchar c)//函数说明:在左页(主窗口)当前地址画一个字节(8点)////////////////////////////////////////////////////////////////////////////////void putchar_l(uchar c){send_md(c);}//////////////////////////////////////////////////////////////////////////////////调用方式:void putchar_r(uchar c)//函数说明:在右页(从主窗口)当前地址画一个字节(8点)////////////////////////////////////////////////////////////////////////////////void putchar_r(uchar c){send_sd(c);}//////////////////////////////////////////////////////////////////////////////////调用方式:void draw_bmp(uchar col,uchar layer,uchar width,uchar *bmp)//函数说明:画一个图,横坐标是col,layer表示上下层,width是图形的宽,高固定16 // bmp是图形指针// 使用Zimo3Pro软件,采用纵向取模,字节倒序得到数据。
51单片机的串口通信程序
∙51单片机的串口通信程序(C语言)∙发布时间:2009-6-2 阅读次数:2551 字体大小: 【小】【中】【大】作者:佚名来源:不详#include <reg52.h>#include<intrins.h>#include <stdio.h>#include <math.h>#define uchar unsigned char#define uint unsigned intsbit Key1 = P2^3;sbit Key2 = P2^2;sbit Key3 = P2^1;sbit Key4 = P2^0;sbit BELL = P3^6;sbit CONNECT = P3^7;unsigned int Key1_flag = 0;unsigned int Key2_flag = 0;unsigned int Key3_flag = 0;unsigned int Key4_flag = 0;unsigned char b;unsigned char code Num[21]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x 02,0x78,0x00,0x10,0x89};unsigned char code Disdigit[4] = {0x7F,0xBF,0xDF,0xEF};unsigned char Disbuf[4];void delayms(uint t){uint i;while(t--){/* 对于11.0592M时钟,约延时1ms */for (i=0;i<125;i++){}}}//-----------------------------------------------------void SendData(uchar Dat) {uchar i=0;SBUF = Dat;while (1){if(TI){TI=0;break;}}}void ScanKey(){if(Key1 == 0){delayms(100);if(Key1 == 0){Key1_flag = 1;Key2_flag = 0;Key3_flag = 0;Key4_flag = 0;Key1 = 1;}else;}if(Key2 == 0){delayms(100);if(Key2 == 0){Key2_flag = 1;Key1_flag = 0;Key3_flag = 0;Key4_flag = 0;Key2 = 1;}else;}if(Key3 == 0){delayms(50);{Key3_flag = 1;Key1_flag = 0;Key2_flag = 0;Key4_flag = 0;Key3 = 1;}else;}if(Key4 == 0){delayms(50);if(Key4 == 0){Key4_flag = 1;Key1_flag = 0;Key2_flag = 0;Key3_flag = 0;Key4 = 1;}else;}else;}void KeyProc(){if(Key1_flag){TR1 = 1;SendData(0x55);Key1_flag = 0;}else if(Key2_flag){TR1 = 1;SendData(0x11);Key2_flag = 0;}else if(Key3_flag){P1=0xff;BELL = 0; CONNECT = 1;}else if(Key4_flag){CONNECT = 0;BELL = 1;Key4_flag = 0;}else;}void Initdisplay(void){Disbuf[0] = 1;Disbuf[1] = 2;Disbuf[2] = 3;Disbuf[3] = 4;}void Display() //显示{unsigned int i = 0;unsigned int temp,count;temp = Disdigit[count];P2 =temp;temp = Disbuf[count];temp = Num[temp];P0 =temp;count++;if (count==4)count=0;}void time0() interrupt 1 using 2 {Display();TH0 = (65535 - 2000)/256;TL0 = (65535 - 2000)%256;}void main(){Initdisplay();TMOD = 0x21;TH0 = (65535 - 2000)/256;TL0 = (65535 - 2000)%256;TR0 = 1;ET0 = 1;TH1 = 0xFD; //11.0592MTL1 = 0xFD;PCON&=0x80;TR1 = 1;ET1 = 1;SCON = 0x40; //串口方式REN = 1;PT1 = 0;PT0 = 1;EA = 1;while(1){ScanKey();KeyProc();if(RI){Disbuf[0] = 0;Disbuf[1] = 20;Disbuf[2] = SBUF>>4;Disbuf[3] = SBUF&0x0f;RI = 0;}else;}}。
51单片机控制nRF24L01收发数据程序
51单片机控制nRF24L01收发数据程序#include#includetypedef unsigned char uchar;typedef unsigned char uint;//****************************************NRF24L01端口定义***************************************sbit M ISO =P1^3;sbit M OSI =P1^4;sbit SCK =P1^2;sbit CE =P1^1;sbit CSN =P3^2;sbit IRQ =P3^3;//************************************按键***************************************************sbit KEY1=P3^6;sbit KEY2=P3^7;//************************************数码管位选*********************************************sbit led0=P2^0;sbit led1=P2^1;sbit led2=P2^2;sbit led3=P2^3;//***********************************数码管0-9编码*******************************************//自己uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9编码//*********************************************NRF24L01************************ *************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 20 // 20 uints TX payload#define RX_PLOAD_WIDTH 20 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接受地址//***************************************NRF24L01寄存器指令******************************************************* #define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接受数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送FIFO指令#define FLUSH_RX 0xE2 // 冲洗接受虵IFO指令#define REUSE_TX_PL 0xE3 // 定义重装载数据指令#define NOP 0xFF // 保留//*************************************SPI(nRF24L01)寄存器地址****************************************************#define CONFIG 0x00#define EN_AA 0x01#define EN_RXADDR 0x02#define SETUP_AW 0x03#define SETUP_RETR 0x04#define RF_CH 0x05#define RF_SETUP 0x06#define STATUS 0x07#define OBSERVE_TX 0x08#define CD 0x09#define RX_ADDR_P0 0x0A#define RX_ADDR_P1 0x0B#define RX_ADDR_P2 0x0C#define RX_ADDR_P3 0x0D#define RX_ADDR_P4 0x0E#define RX_ADDR_P5 0x0F#define TX_ADDR 0x10#define RX_PW_P0 0x11#define RX_PW_P1 0x12#define RX_PW_P2 0x13#define RX_PW_P3 0x14#define RX_PW_P4 0x15#define RX_PW_P5 0x16#define FIFO_STATUS 0x17//************************************************************* **************** *********void Delay(unsigned int s);void inerDelay_us(unsigned char n);void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);//*****************************************长延时*****************************************void Delay(unsigned int s){unsigned int i;for(i=0; i<="" p="">for(i=0; i<="" p="">}//************************************************************* **************** *************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/************************************************************** **************** ************/*延时函数/************************************************************** **************** ************/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//************************************************************* **************** ***********/*NRF24L01初始化//************************************************************* **************** **********/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; //SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);SPI_RW_Reg(WRITE_REG + RF_CH, 0);SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);}/************************************************************** **************** **********************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序序/************************************************************** **************************************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again}return(uchar); // return read uchar}/************************************************************** **************** **********************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序/************************************************************** **************** **********************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN low, initialize SPI communication...SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN = 1; // CSN high, terminate SPI communicationreturn(reg_val); // return register value}/************************************************************** **************** **********************//*功能:NRF24L01读写寄存器函数/************************************************************** **************** **********************/uint SPI_RW_Reg(uchar reg, uchar value){uint status;CSN = 0; // CSN low, init SPI transactionstatus = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN = 1; // CSN high againreturn(status); // return nRF24L01 status uchar}/************************************************************** **************** **********************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读数据地址,uchars:读出数据的个数/************************************************************** **************** **********************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)<bdsfid="230" p=""></uchars;uchar_ctr++)<>pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/************************************************************** **************** ***************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/****************************************************************** ************ ***************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0;status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<="">SPI_RW(*pBuf++);CSN = 1;return(status);}/************************************************************** **************** **********************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/************************************************************** **************** **********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);CE = 1;inerDelay_us(130);}/************************************************************** **************** ************************//*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后如rx_buf接受缓冲区中/************************************************************** **************** ************************/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) {unsigned char revale=0;sta=SPI_Read(STATUS);if(RX_DR){CE = 0;SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);revale =1;}SPI_RW_Reg(WRITE_REG+STATUS,sta);return revale;}/************************************************************** **************** *****************************/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送tx_buf中数据/************************************************************** **************** ****************************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0;SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);CE=1;inerDelay_us(10);}//************************************主函数*********************************************************** void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0};unsigned char RxBuf[20]={0};init_NRF24L01() ;led2=0;led3=0;led0=0;led1=0;// P0=0x00;TxBuf[1] = 1 ;TxBuf[2] = 1 ;nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(6000);// P0=0xBF;while(1){if(KEY1 ==0 ){led2=1;//自己P0=seg[1];TxBuf[1] = 1 ;tf = 1 ;}if(KEY2 ==0 ){//自己P0=seg[2];led3=1;TxBuf[2] =1 ;tf = 1 ;if (tf==1){nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataTxBuf[1] = 0x00;TxBuf[2] = 0x00;tf=0;Delay(1000);}//************************************************************* **************** ******************SetRX_Mode();nRF24L01_RxPacket(RxBuf);if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led0=1;//ziji P0=seg[3];}if( RxBuf[2]==1){led1=1;//ziji P0=seg[4];}Delay(1000);}RxBuf[1] = 0x00;RxBuf[2] = 0x00;}。
51单片机的串口通信程序之欧阳化创编
单片机串口通信程序创作:欧阳化#inelude <reg52.h> #include<intrins.h>#include<stdio.h>#include <math.h>#define uchar unsigned char #define uint unsigned int sbit Keyl = P2A3;sbit Key2 = P2A2;sbit Key3 = P2A1;sbit Key4 = P2A0;sbit BELL = P3A6;sbit CONNECT = P3A7;unsigned int Keyl_flag = 0;iinsigned int Key2_flag = 0;unsigned int Key3_flag = 0;unsigned int Key4_flag = 0;unsigned charb;unsigned char codeNum[21] = {0xc0,0xf9,0xa4, OxbO, 0x99,0x92,0x82z 0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12, 0x02,0x78,0x00, 0x10,0x89}; unsigned char code Disdigit[4]= {0x7F,0xBF,0xDF,0xEF};unsignedchar Disbuf[4];void delayms(uint t){ uint i; while(t--) { /* 对于11.0592M 时钟,约延时 1ms */ for (i=0;i<125;i + +) {} }}//void SendData(uchar Dat){uchar i=0;SBUF = Dat;while(1) { if(TI) { H=o ; break; } }} void SeanKey(){ if(Keyl ==0) { delayms(lOO); if(Keyl ==0) { Keyljlag = 1; Key2Jlag = 0; Key3Jlag = 0; Key4Jlag = 0; Keyl =1;} else; } if(Key2 == 0) { delayms(lOO); if(Key2 ==0) { Key2Jlag = 1; Keyljlag = 0; Key3Jlag = 0; Key4Jlag = 0; Key2 =1;} else; } if(Key3 == 1; SendData(0x55); Keyljlag = 0; } else0) { delayms(50); if(Key3 == 0) { =1; Keyl_flag = 0; Key2_flag = 0; 0; Key3 = 1; }else; } if(Key4 ==0) { delayms(50); if(Key4 == 0) { =1; Keyl_flag = 0; Key2_flag = 0;0; Key4 = 1; } else; } else; }voidKeyProc(){ if(Keyl_flag) { TRI =Key3JlagKey4_flag = Key4JlagKey3Jlag =if(Key2_flag) { TRI =1; SendData(Oxll); Key2_flag = 0; } elseif(Key3_flag) { Pl=Oxff; BELL = 0; CONNECT =1; Key3_flag = 0; ) else if(Key4_flag) { CONNECT =0; BELL = 1; Key4_flag = 0; } else; }void Initdisplay(void){Disbuf[0] = l;Disbuf[l] = 2;Disbuf[2]=3;Disbuf[3] = 4;}void DisplayO 〃显示{unsigned int i = 0;unsignedint temp,count; temp = Disdigit[count]; P2=temp; temp = Disbuf[count]; temp =Num [temp]; P0=temp; count++; if (count==4) count =0; ) void timeOO interrupt 1 using2{ DisplayO; THO = (65535 ・ 2000)/256; TLO = (65535 ・2000)%256;} void main(){Initdisplay();TMOD = 0x21;TH0 = (65535 ・ 2000)/256;TL0 = (65535 ・ 2000)%256;TR0 = 1;ETO = 1; TH1 = OxFD;//11.0592MTL1 = OxFD;PCO N&=0x80;TRl = 1;ET1 = 1;SCON = 0x40; 〃串口方式REN = 1; PT1 = O;PTO = 1;EA =1;while(l) { ScanKeyO; KeyProc(); if(RI) { D isbuf[O] = 0; Disbuf[l] = 20; Disbuf[2]=SBUF>>4; Disbuf[3]二SBUF&0x0f; RI = 0; } else; }}。
单片机C51串口中断接收和发送测试例程(含通信协议的实现)
通信协议:第1字节,MSB为1,为第1字节标志,第2字节,MSB为0,为非第一字节标志,其余类推……,最后一个字节为前几个字节后7位的异或校验和。
测试方法:可以将串口调试助手的发送框写上95 10 20 25,并选上16进制发送,接收框选上16进制显示,如果每发送一次就接收到95 10 20 25,说明测试成功。
//这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的#include <reg51.h>#include <string.h>#define INBUF_LEN 4 //数据长度unsigned char inbuf1[INBUF_LEN];unsigned char checksum,count3;bit read_flag= 0 ;void init_serialcomm( void ){SCON = 0x50 ; //SCON: serail mode 1, 8-bit UART, enable ucvrTMOD |= 0x20 ; //TMOD: timer 1, mode 2, 8-bit reloadPCON |= 0x80 ; //SMOD=1;TH1 = 0xF4 ; //Baud:4800 fosc=11.0592MHzIE |= 0x90 ; //Enable Serial InterruptTR1 = 1 ; // timer 1 run// TI=1;}//向串口发送一个字符void send_char_com( unsigned char ch){SBUF=ch;while (TI== 0 );TI= 0 ;}//向串口发送一个字符串,strlen为该字符串长度void send_string_com( unsigned char *str, unsigned int strlen){unsigned int k= 0 ;do{send_char_com(*(str + k));k++;} while (k < strlen);}//串口接收中断函数void serial () interrupt 4 using 3{if (RI){unsigned char ch;RI = 0 ;ch=SBUF;if (count3> 127 ){count3= 0 ;inbuf1[count3]=ch;checksum= ch- 128 ;}else{count3++;inbuf1[count3]=ch;checksum ^= ch;if ( (count3==(INBUF_LEN- 1 )) && (!checksum) ){read_flag= 1 ; //如果串口接收的数据达到INBUF_LEN个,且校验没错,//就置位取数标志}}}}main(){init_serialcomm(); //初始化串口while ( 1 ){if (read_flag) //如果取数标志已置位,就将读到的数从串口发出{read_flag= 0 ; //取数标志清0send_string_com(inbuf1,INBUF_LEN);} }}。