串口发送接收数据乱码

andy_James 2010-05-07 04:42:33
我的单片机串口发送和接收数据的时候老是乱码,波特率的设置我已经试过各种了,还是一样,请问这个问题如何解决呢?
...全文
7282 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
庚瓒 2012-04-28
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 的回复:]
接收发送这些都可以了,但是我遇到了新的问题:
就是在调用我的发送函数前添加个延时几百毫秒则发送正常,可是不加延时函数的话在某些情况会出现乱码。例如我的程序一直在跑,我用串口调试助手的接收的时候正确,可是当我只是把助手断开连接再连接上的时候可能就会出现乱码,助手的提示为RichEdit line insertion error,虽然出现乱码,可是有时候当我多次断开助手再连接的时候有时候又能正确的发……
[/Quote]不知道楼主问题解决了没有 我使用STM32的板子也遇到了类似的问题:程序功能是在一个无限循环里面扫描两个按键的状态,按键按下时分别发送点和划,比如我按下键1,发送点,按下键2发送划。但是在PC端的串口调试助手里接收到的不一样,有时应该是一个点却接收到很多点,反正个数不确定。在发送函数前加延迟就好点,偶尔能正确接收。。。如果楼主知道的话解释下,谢谢!
啸风在学习 2012-04-21
  • 打赏
  • 举报
回复
我今天用无线串口也是出现同样的问题,第一次用
andy_James 2010-05-17
  • 打赏
  • 举报
回复
接收发送这些都可以了,但是我遇到了新的问题:
就是在调用我的发送函数前添加个延时几百毫秒则发送正常,可是不加延时函数的话在某些情况会出现乱码。例如我的程序一直在跑,我用串口调试助手的接收的时候正确,可是当我只是把助手断开连接再连接上的时候可能就会出现乱码,助手的提示为RichEdit line insertion error,虽然出现乱码,可是有时候当我多次断开助手再连接的时候有时候又能正确的发送到助手(没乱码),对了,还有时候在我断开助手再连接的时候有时候助手接收不到数据。注:波特率的误差就 0.1%。
请哪位大虾给我解释解释,谢谢!
chutianya 2010-05-17
  • 打赏
  • 举报
回复
你的串行通信是单片机发送数据给pc,那么请问你的单片机是怎么发送数据的啊?是直接把一个你定义的数据存储区的数据发给pc,还是通过键盘中断来发送数据?如果是直接发送那就有问题了。因为你那个发送函数一般也没有握手的过程,单片机那边的数据复位就马上发送过去了,你那个串口助手可能还没有准备好接受呢。
一般来说,发送函数前加一个延时是没必要的吧。应该没有什么影响。。。。。
andy_James 2010-05-13
  • 打赏
  • 举报
回复
我的datasheet里面没说什么,图片就发送接收数据的时序图,我不晓得如何去计算。
galle 2010-05-13
  • 打赏
  • 举报
回复
你发送的是十六进制还是ascii码方式,你接受到数据后按照什么方式处理的!
有乱码说明受到东西了!
chutianya 2010-05-12
  • 打赏
  • 举报
回复
乱码还是波特率的设置问题。你那个波特率计算公式不对,所以你初始化设置的实际初值与你计算的数值时不相等的。波特率不对就会出现乱码。我的那个串口发送机就是这样,波特率公式不对。还有就是你发送和接收的格式要想好,调节准确。。。这样你实验几下就行了。如果你的晶振是11.0592M的话,那么9600波特率的初值是TH1=TL1=0xfd;SMOD=0;如果是电脑发送给单片机的话,那么你发送的一般来说默认的是ASSIIC码形式,你那边接收也显示也要是ASSIIC码格式。再自己试试就差不多了。。。。
HuWenjin 2010-05-12
  • 打赏
  • 举报
回复
楼上的是用于单片机通信的吗? 写得这么复杂啊

是什么单片机?

反正要注意的是必须要等发送或接收完成后再发送。

因为单片机中一般只有一个SBUF 又收又发的,没有收完就发了,两边都乱了,收的是乱的,发的也是乱的。

如果是单片机,建议:http://blog.csdn.net/Saimen/archive/2010/05/11/5580740.aspx

搞个程序,自动生成好了
HuWenjin 2010-05-12
  • 打赏
  • 举报
回复
当然不是用初始化设置,是用一整套的
http://item.taobao.com/auction/item_detail-0db2-4f09e6476eb55c8fe0a317d59cfb3b33.htm
andy_James 2010-05-12
  • 打赏
  • 举报
回复
为什么我用这个初始化设置,在我接收一个字符的时候就是乱码了呢?
mj_17 2010-05-12
  • 打赏
  • 举报
回复
波特率设置跟你的单片机晶体有关.如何计算和设置请参考datasheet.
andy_James 2010-05-12
  • 打赏
  • 举报
回复
我不知道如何去计算波特率,我用示波器测了波形图出来了不知道如何计算
HuWenjin 2010-05-12
  • 打赏
  • 举报
回复
#define GetSystemClock() (80000000ul) 这是多少晶震?8千万? 80M ?

下载一个软件自己生成一下都不想搞?还非要等别人给你生成好?

假定晶震是8MHZ的,很难产生一个准确的波特率,用定时器1

//////////////////////////////////////////////////////////////////////////
// 名称: SIO_Init
// 说明: 8.0MHZ晶震下初始化串口波特率为1200bps
// 8位数据位,1位停止位,无校验
// 返回: void
void SIO_Init(void)
{
//////////////////////////////////////
// 禁止串口中断
ES = 0;

//////////////////////////////////////
// SCON
// D7 D6 D5 D4 D3 D2 D1 D0
// SM0 SM1 SM2 REN TB8 RB8 TI RI
// 0 1 0 0 0 0 0 0
//
// SM0=0 SM1=1 -> 8位UART 波特率可变
SCON = 0x40;

//////////////////////////////////////
// TMOD
// D7 D6 D5 D4 D3 D2 D1 D0
// GATA C/T M1 M0 GATA C/T M1 M0
// 0 0 1 0 ? ? ? ?
//
// 定时器1定时方式2说明:
// 把16位计数器分为两部分,即以TL0为计数器,
// 以TH0作为预置寄存器。初始化时把计数初值分别
// 加载至TL和TH中。当计数溢出时,由预置寄存器TH
// 以硬件方法自动给计数器TL重新加载。
//
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xDD;
TL1 = 0xDD;

//////////////////////////////////////
// PCON
// D7 D6 D5 D4 D3 D2 D1 D0
// SMOD - - - GF1 GF0 PDWN IDLE
PCON |= 0x80;

//////////////////////////////////////
TR1 = 1;// 启动定时器
REN = 1;// 允许串口接收数据
ES = 1;// 开启串口中断

//////////////////////////////////////
// EA
// D7 D6 D5 D4 D3 D2 D1 D0
// EA - ET2 ES ET1 EX1 ET0 EX0
//
// 建议在全部初始化完成后,在主程序中启用
// EA = 1;
//
}



8M 用 1200bps 定时器1,还可以将就用一下, -0.83%的误差。
如果晶震本身再不准,估计就更难不乱码了
mww_520 2010-05-11
  • 打赏
  • 举报
回复
波特率设置是否正确?显示模式是否正确?
HuWenjin 2010-05-11
  • 打赏
  • 举报
回复
Jin51SIO是什么?

Jin51SIO 是一个自动生成单片机串口通信操作函数集的程序
Jin51SIO 是一套单片机串口操作的API函数集。

Jin51SIO能作什么?

1.只需要点几下鼠标,便可针对不同的晶震、不同的的波特率生成一套操作串口的源程序代码。
2.中断方式的接收数据
3.中断方式的发送数据,减少因等待发送而占用CPU时间
4.漂亮的环形队列处理,很少的缓冲空间解决大问题
5.提供SIO_VSend函数,可以格式化输出变量,例如:SIO_VSend("U=%.2f",fU);方便调试程序
6.能高效的、稳定的完成通信操作。

为什么要选用Jin51SIO?

1.出于研究的目的
Jin51SIO不是教学程序,而是作者多年的经验总结。可以研究作者的程序流程,程序格式应用到类似的项目中,并不一定是单片机串口通信。例如简洁的的环形队列操作,在很多程序中都可以应用。

2.可靠的完成项目
无需记忆串口设置中的相关参数,只需点击鼠标便自动生成。全部代码保留在可执行程序中,不会被外部修改;始终得到可靠的源码文件。

3.高效的进行程序修改调试
当需要测试不同波特率时,只需要点几下鼠标便生成了对应的代码。这只是几秒钟的事。同时提供了格式化输出函数,可以直接将内存变量通过串口输出到控制台或其它调试程序。

4.不受idata data区大小限制的收发缓冲
缓冲区在xdata区,可以设置为你想要的大小而不受128、256字节的限制,同时可以节约下这些高速访问区用于采样等。

5.节约时间,提高效率
现在的社会,时间就是一切。使用Jin51SIO后,可以一天内掌握单片机串口操作的真正流程。如果您看过Jin51SIO的代码,将会发现和网络上流传的那些单片机通信例程有什么不同了。
在新的项目中不用花时间解决串口通信问题。


http://item.taobao.com/auction/item_detail-0db2-4f09e6476eb55c8fe0a317d59cfb3b33.htm
andy_James 2010-05-11
  • 打赏
  • 举报
回复
每次接受到的数据都跟我传进来的不同,每次发送出去的也是乱码,可是我觉得我初始化里面没错呀!大虾帮我看看:
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock() / (1<<OSCCONbits.PBDIV))
#define GetInstructionClock() (GetSystemClock())

#define DESIRED_BAUDRATE (9600)
SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY );

UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
UINT BD;
BD =UARTSetDataRate(UART1, GetPeripheralClock(), DESIRED_BAUDRATE);
UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
INTSetVectorPriority(INT_VECTOR_UART(UART1), INT_PRIORITY_LEVEL_2);
INTSetVectorSubPriority(INT_VECTOR_UART(UART1), INT_SUB_PRIORITY_LEVEL_0);
// configure for multi-vectored mode
INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
// enable interrupts
INTEnableInterrupts();
应该没问题吧,我找了好久都没找出问题的根源,不知道如何解决乱码。
Peasant_Lee 2010-05-08
  • 打赏
  • 举报
回复
假如有示波器的话,楼主,可以从根源一步一步的跟踪UART信号。看到哪里出问题了。。
x11223y 2010-05-07
  • 打赏
  • 举报
回复
具体问题具体分析,慢慢调试
hyljx1219 2010-05-07
  • 打赏
  • 举报
回复
奇偶校验什么的所有的硬件设置特别是波特率是不是正确!?感觉应该是这方面的问题,再有就是232芯片的外接电容是不是合适呢?
hjf0102 2010-05-07
  • 打赏
  • 举报
回复
一定是晶振没有选用了11.0592MHZ
加载更多回复(8)

27,377

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧