打印
[STM32F2]

串口1使用不正常,输出错误

[复制链接]
3624|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
奥义u|  楼主 | 2014-6-14 14:06 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
STM32新手,分数少不要嫌弃~~~

// usart.c
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);        
}
void Uart_Init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
uchar temp;
temp++;

// PA9 -- TX PA10 -- RX
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);  
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//NVIC_Config();
}
void UART1Write(uchar* data,uint len)
{
u16 i;
  for(i=0; i<len; i++)
   UART1_SendBuf[i] = data[i];
  UART1_SendSum = len;
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
    for (i=0; i<len; i++)
    {
        USART_SendData(USART1, data[i]);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
        {
            ;
        }
    }
}
void USART1_IRQHandler(void)
{   
     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        UART1_BUF[UART1_COUNT++] = USART_ReceiveData(USART1);  //接收数据
        if(UART1_COUNT >= UART1BUF_SIZE_MAX)        //超过最大缓存,清零计数
        {
            UART1_COUNT = 0;
        }
    }
}

// main.c
uchar array[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
SystemInit();
while(1)
{
  UART1Write(array, 1);
}

//-------------------------程序分割线------------------------------------
以上是usart.c和main.c中的内容 省略了头文件和一些参数的声明
遇到了两个问题:
1.发送的数据错误,不是0xaa,而是别的值。测试过Tx脚的波特率,应该是正确的,不知道是什么原因了,求解。
2.如果//NVIC_Config();去掉注释,则程序会一直死在里面出不来,后面的数据也不会发送。
以上配置都是从其他贴子中复制过来的,不知道错在哪里。
沙发
icecut| | 2014-6-14 16:24 | 只看该作者
从官方提供的库里拷贝代码.网上的代码正确的太少了.因为有问题才贴出来问

使用特权

评论回复
板凳
mmuuss586| | 2014-6-14 17:18 | 只看该作者
程序仔细看了下,没啥问题;
1、程序跟踪下,看发的是不是0XAA;
   或者将发送和输出短接,通过串口中断看看,收到的是啥数据;
2、中断初始化和发送没啥关系,当然你出现的问题,不好猜;
你可以先用官方例程试下,搞不好你工程设置,程序优化级别设置等不合理……

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
奥义u + 1 很给力!
地板
奥义u|  楼主 | 2014-6-16 10:42 | 只看该作者
mmuuss586 发表于 2014-6-14 17:18
程序仔细看了下,没啥问题;
1、程序跟踪下,看发的是不是0XAA;
   或者将发送和输出短接,通过串口中断看 ...

        按照你所说的,我把Rx和Tx短接,取消了发送中断,在while中采用USART_SendData(USART1, 0xaa);循环发送,采用中断接收数据,果然发现接收到的是正确的数据
    可是我通过串口调试助手接收到的数据还是错误的。串口调试助手的配置也是常规(波特率:115200;数据位:8;停止位:1;校验位:NONE;流控制:NONE),也试过更换串口下载器,始终无法接收到正确的数据,这又是为什么

使用特权

评论回复
5
dingsujie| | 2014-6-16 14:12 | 只看该作者
你是不是调试助手上的输出为HEX没有点勾啊

使用特权

评论回复
6
奥义u|  楼主 | 2014-6-16 14:46 | 只看该作者
dingsujie 发表于 2014-6-16 14:12
你是不是调试助手上的输出为HEX没有点勾啊

点了的

使用特权

评论回复
7
想做大牛的小马| | 2014-6-16 15:09 | 只看该作者
奥义u 发表于 2014-6-16 14:46
点了的

自环没有问题,说明发出来的看起来是对的呀,调试工具接收到的是什么?有没有错位之类的,用系统自带的超级终端看看呢~

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
奥义u + 1 很给力!
8
奥义u|  楼主 | 2014-6-16 17:08 | 只看该作者
想做大牛的小马 发表于 2014-6-16 15:09
自环没有问题,说明发出来的看起来是对的呀,调试工具接收到的是什么?有没有错位之类的,用系统自带的超 ...

也不一定,又看了下数据手册,上面对Data register(USART_DR)的解释中说到“Contains the Received or Transmitted data character,
depending on whether it is read from or written to.”说的是接收和发送是共用这个数据寄存器的把,那么自环只能说明写入的数据没有问
题吧,至于发送出的数据有没有问题还是无法说明的吧。

上图是发送0xaa,用示波器检测Tx脚获得的波形图,也是不对的吧。。。

使用特权

评论回复
9
想做大牛的小马| | 2014-6-16 17:33 | 只看该作者
奥义u 发表于 2014-6-16 17:08
也不一定,又看了下数据手册,上面对Data register(USART_DR)的解释中说到“Contains the Received or  ...

0xaa -- 10101010b 看波形好像有1bit错误,确认一下奇偶校验位有没有使能,发一组0x55,0xaa看看呢~

使用特权

评论回复
10
奥义u|  楼主 | 2014-6-16 19:03 | 只看该作者
想做大牛的小马 发表于 2014-6-16 17:33
0xaa -- 10101010b 看波形好像有1bit错误,确认一下奇偶校验位有没有使能,发一组0x55,0xaa看看呢~ ...

1.发送0xaa,串口调试助手收到的是0x98,0xe6;
2.发送0x55,串口调试助手收到的数据和示波器显示如下图:

使用特权

评论回复
11
想做大牛的小马| | 2014-6-16 19:17 | 只看该作者
好诡异哦。。发先不要用中断试试吧。。。把write函数中的itconfig先注释掉看看呢

使用特权

评论回复
12
dingsujie| | 2014-6-17 08:58 | 只看该作者
你把发送中断给关了;采用直接发送;每隔1S发送一次0xaa;把NVIC关闭掉

使用特权

评论回复
13
奥义u|  楼主 | 2014-6-17 15:35 | 只看该作者
        找到问题错误的大致方向了,波特率不对。选择输出0x55,可以从示波器的图形看出,翻转一次的时间在220us左右,
算出波特率在4500左右,把串口调试助手的波特率改成4800,哈哈,果然输出了0x55~~~
       可是使用的函数都是库提供的,按理说没有理由出现这个问题啊???看了好久的芯片手册也看了半天的官方的历程都
没搞明白,各位提提该如何解决下一步的问题啊@dingsujie @想做大牛的小马 @mmuuss586 @icecut  

使用特权

评论回复
14
icecut| | 2014-6-17 15:44 | 只看该作者
奥义u 发表于 2014-6-17 15:35
找到问题错误的大致方向了,波特率不对。选择输出0x55,可以从示波器的图形看出,翻转一次的时间在 ...

有示波器就容易多了.你看看你晶振是不是准,如果准就看时钟树,与串口有关的看看设置成多少了.
实际是4800你想设置成多少频率?

使用特权

评论回复
15
奥义u|  楼主 | 2014-6-17 15:51 | 只看该作者
icecut 发表于 2014-6-17 15:44
有示波器就容易多了.你看看你晶振是不是准,如果准就看时钟树,与串口有关的看看设置成多少了.
实际是4800 ...

问题是配置的时候是USART_InitStructure.USART_BaudRate = 9600;结果确实4800

使用特权

评论回复
16
dingsujie| | 2014-6-17 16:07 | 只看该作者
你先确认采用的是8MHZ晶振;然后做如下修改:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);   
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
你试试,我估计是红色这条你写错了

使用特权

评论回复
17
mmuuss586| | 2014-6-17 16:10 | 只看该作者
奥义u 发表于 2014-6-17 15:35
找到问题错误的大致方向了,波特率不对。选择输出0x55,可以从示波器的图形看出,翻转一次的时间在 ...

先把系统时钟啥的读出来看看。一步步查

使用特权

评论回复
18
想做大牛的小马| | 2014-6-17 16:11 | 只看该作者
奥义u 发表于 2014-6-17 15:35
找到问题错误的大致方向了,波特率不对。选择输出0x55,可以从示波器的图形看出,翻转一次的时间在 ...

嗯,都定位到是时钟问题了啊,厉害厉害,用的是uart 几啊?USART_BRR寄存器里的值读出来看看是多少?
然后确定一下APB1和APB2的时钟是多少,uart1,6挂在apb1,其它的在apb2上~

使用特权

评论回复
19
奥义u|  楼主 | 2014-6-18 14:54 | 只看该作者
问题解决了。
USART1是由PCLK2提供时钟,故读取如下的值:
  apbclock_SYSCLK = RCC_ClocksStatus.SYSCLK_Frequency;// 系统时钟
  apbclock_PCLK2 = RCC_ClocksStatus.PCLK2_Frequency; //PCLK2值
  Uart_Init();     // 使用的波特率是9600
  baud_div = USART1->BRR;    // 串口分频值
可以读出apbclock_SYSCLK = 0x7270E0000(120M)
apbclock_PCLK2 = 0x3938700(60M)
baud_div = 0x186A(6250)
计算baudrate = apbclock_PCLK2 / baud_div = 9600 一切都是如此完美
可,这一切都是假象,在stm32f2xx.h中有这么一句
#define HSE_VALUE            ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
原来这里把外围晶振定义为了25MHZ,修改为12MHZ,
从新读取apbclock_SYSCLK = 0x57600000(57.6M)
apbclock_PCLK2 = 0x28800000(28.8M)
baud_div = 0xBB8(3000)
USART1使用的实际频率是28.8MHZ,28800000 / 6250 = 4608(实际的波特率) 原来这才是真相啊
之后修改了RCC寄出器一些寄存器的值,使系统时钟达到120MHZ就可以了
谢谢大家的帮忙!!!

使用特权

评论回复
20
奥义u|  楼主 | 2014-6-24 10:36 | 只看该作者
不会结贴,日啊。。。:dizzy:

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

14

帖子

0

粉丝