首页 > 编程知识 正文

半双工通信只有一个,51单片机串口接收数组

时间:2023-05-06 21:17:47 阅读:17350 作者:4671

优化《51单片机——UART串口通讯-波特率可选,增添定时器2产生波特率1.1版本》的代码。

2、主要修改了串行发送和串行中断的代码,增加了串行发送识别位、串行接收完成识别位、接收缓冲器50字节。

3、这段代码在半双工模式下工作。

4、使用系统输出函数后,用自定义函数发送需要2毫秒的延迟,否则会出错。

测试结果:计时器1、计时器2波特率均验证OK。 4800bps~115200bps

main.c

# include ' UART.h ' # include stdio.h # include ' delay.h ' # define UART _ t1//1则计时器1表示波特率,0则计时器2表示波特率//这是串行端口半双工模式。调试delay至少需要2毫秒的延迟(如果使用系统输出函数) (voidmain ) void )//puts,然后换行(if(UART_T1 ) init_config //要使用printf将串行端口的波特率初始化为最大57600ES=0,请首先关闭串行并中断TI=1; //在使用系统函数之前使TI达到1puts(1,计时器2产生波特率,测试结果通过); printf(2,计时器2产生波特率,测试结果为pass(n ); ES=1; //启动串行端口并停止delay_ms(2; //不知道为什么需要延迟,否则接收数据时会出错的UART_send_string(rx ); //发送默认数据}else{UART_T2_init_config(1; //要使用printf将串行端口的波特率初始化为最大115200ES=0,请首先关闭串行并中断TI=1; //在使用系统函数之前使TI达到1puts(1,计时器2产生波特率,测试结果通过); printf(2,计时器2产生波特率,测试结果为pass(n ); ES=1; //启动串行端口以中断delay_ms(2; //不知道为什么需要延迟,否则接收数据时会出错的UART_send_string(rx ); //发送默认数据}while(1) if ) flag_rx ) Uart_send_string ) rx ); flag_rx=0; }}} delay.c和delay.h

太简单了。 自己处理吧。

uart.h

# ifndef _ _ UART _ h _ # define _ _ UART _ h _ _ # includereg 52.h//mode _ n _ bps输入示例,计时器1为115200//////bbps //最多保存50字节//串行端口初始化装载,并使用计时器1生成波特率。 默认值为9600 bpsvoiduart _ t1 _ init _ config (unsignedcharmode _ n _ bps ); //串行端口初始化负载,使用计时器2生成波特率//串行端口的工作方式1,8位uart时波特率可变,串行端口数据//允许接收默认波特率9600 bpsvoiduart _ T2 _ init _ config (unsignedcharmode _ n _ bps )//串行发送数据void UART _ send _ //串行发送字符串void UART _ send _ string (unsigned char * c ); #endif //! __UART_H__ uart.c

#include 'uart.h'sfr IPH_=0xB7; //中断优先级高位寄存器sfr SADEN_=0xB9; //从站地址屏蔽寄存器sfr SADDR_=0xA9; //从站地址控制寄存器static bit flag_tx=0; //发送空闲显示位bit flag_rx=0; //接收忙标志unsigned char RX[53]={ '请记住,最多只能发送二十五个汉字,最后需要回车。 丙rn'} '; //最多初始化装载超过50字节//串行端口,使用计时器1生成波特率//串行端口的动作方式1、8位uart,使波特率可变,串行端口为数据//计时器1的动作方式2、 允许8位自动重载模式void uart _ t1 _ init _ config (unsignedcharmonfig )//串行端口的工作方式为1,8位UART,波特率可变,串行端口为数据//最高SMOD=1表示串行端口操作模式1、2、3下的双倍波特率(默认PCON=0x10,波特率不加倍) SADEN_=0x00; 不使用SADDR_=0x00; 不使用TI=0清除RI=0清除ea=1//打开总中断的ES=1; //打开串行端口中断//串行端口1中断优先级0IPH_=0x00; IP=0x00; TMOD |=0x20; //打开计时器T1,以切换操作模式2(8位自动重载) switch(mode_n_bps ) {case 1:TL1=250; //计数初始值设定波特率4800bpsTH1=250; //固定初始值,当TL1充满时自动将TH1的值加载到break中; //b

ps4800case 2:TL1 = 253;//计数初值设置波特率9600bpsTH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去break;//bps9600case 3:PCON |= 0x80;//SM0D=1,波特率加倍TL1 = 253;//计数初值设置波特率19200bpsTH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去break;//bps19200case 4:PCON |= 0x80;//SM0D=1,波特率加倍TL1 = 255;//计数初值设置波特率57600bpsTH1 = 255;//装载固定初值,当TL1加满后会自动把TH1的值装载进去break;//bps57600default://默认bps9600TL1 = 253;//计数初值设置波特率9600bpsTH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去break;//bps9600}ET1 = 0;//禁止定时器1发出中断TR1 = 1;//启动定时器1}//串口初始化装载,使用定时器2产生波特率//串口工作方式1,8位uart且波特率可变,且允许串口接收数据void UART_T2_init_config(unsigned char Mode_n_bps)//默认波特率9600bps{SCON = 0x50;//串口工作方式1,8位uart且波特率可变,且允许串口接收数据T2CON |= 0x30;//定时器2用作串口波特率发生器且16位自动重装模式SADEN_ = 0x00;//不使用,默认值SADDR_ = 0x00;//不使用。默认值TI=0;//清除,建议清除一下RI=0;//清除EA = 1;//打开总中断ES = 1;//打开串口中断//串口1中断优先级0IPH_ = 0x00;//默认值IP = 0x00;//默认值//T2MOD = 0x02;//T2OE :T2 输出允许位,当 T2OE=1 的时候,允许时钟输出到 P1.0。(仅对80C54 / 80C58 有效)//DCEN:向下计数允许位。 DCEN = 1 是允许 T2 向下计数,否则向上计数。switch (Mode_n_bps){case 1:TL2 = 0xb8;//计数初值设置波特率4800bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xb8;RCAP2H = 0xff;break;//bps4800case 2:TL2 = 0xdc;//计数初值设置波特率9600bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xdc;RCAP2H = 0xff;break;//bps9600case 3:TL2 = 0xee;//计数初值设置波特率19200bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xee;RCAP2H = 0xff;break;//bps19200case 4:TL2 = 0xfa;//计数初值设置波特率57600bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xfa;RCAP2H = 0xff;break;//bps57600case 5:TL2 = 0xfd;//计数初值设置波特率115200bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xfd;RCAP2H = 0xff;break;//bps115200default://默认bps9600TL2 = 0xdc;//计数初值设置波特率9600bpsTH2 = 0xff;//装载固定初值RCAP2L = 0xdc;RCAP2H = 0xff;break;//bps9600}TR2 = 1;//启动定时器2}//串口发送数据void UART_Send_1Byte_Data(unsigned char DAT){while(flag_tx);//等待之前的数据发送完成flag_tx=1;SBUF = DAT;//如果使用while(!TI);//可能会出现TI=1时刚好进入串口中断,然后串口中断将TI=0;此时程序会卡死在while里的}//串口发送字符串void UART_Send_string(unsigned char *c){do{UART_Send_1Byte_Data(*c++);//带*c表示的是值,c表示的是地址}while (*c != '');}//串口中断函数,中断号4//单片机串口只缓存1字节8位数据void UART_IT(void) interrupt 4{static unsigned char num=0;if (TI) //发送标志位{TI = 0;flag_tx=0;//使用printf()/puts()/putchar()(stdio.h)的时候,需要ES=0;TI=1;printf();(TI=0,printf使用后会自动清除)最后ES=1。}if (RI) //接收标志位{RX[num]=SBUF;//将接收的数据先保存起来//把串口接收到的值在重新发送回去,如果接收数据很大有丢失数据风险RI = 0;if(RX[num]=='n'){num++;RX[num]='';//为的是使用字符串发送数据flag_rx = 1;//数据接收完毕num=0;//清零,使其下次得到的数据开始从0开始存储}else{switch(++num){case 53:num=0;break;}}}}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。