打印
[STM32L0]

STM32F051串口问题求助

[复制链接]
2626|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Enixfaver|  楼主 | 2015-12-30 16:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
初学者一枚
目前串口照着手册配置,一只处于高电平3.3v,没有数据发送,想问下是不是哪里配置配错了,谢谢各位

void USART_Configuration(void)//串口初始化函数
  {  

        GPIO_InitTypeDef  GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        USART_ClockInitTypeDef USART_ClockInitStructure;
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);         
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);


        USART_ClockInitStructure.USART_Clock =  USART_Clock_Enable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_ClockInit(USART1, &USART_ClockInitStructure);
        
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);        

                              
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;                 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        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_ClearFlag(USART1, USART_IT_RXNE);                         //清中断,以免一启用中断后立即产生中断
        USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);                //使能USART1中断源
        USART_ITConfig(USART1, USART_IT_TC, ENABLE);       

        USART_Cmd(USART1, ENABLE);//使能串口1

                }                       
沙发
lvyuan111| | 2015-12-30 16:52 | 只看该作者
不太懂。。。看看有没有其他人帮助吧

使用特权

评论回复
板凳
Enixfaver|  楼主 | 2015-12-30 16:52 | 只看该作者
新手刚接触,问的问题比较低级,还请多包涵

使用特权

评论回复
地板
Huge2015| | 2015-12-30 17:41 | 只看该作者
同为新手,参考例子配置的串口,测试可用。

void GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable GPIOA, GPIOB and GPIOF Peripheral clock */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOF, ENABLE);

  /* USART1(PB6->TX, PB7->RX) Pins Configuration */
  /* Connect pin to Peripheral */
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_0);
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_0);   
  /* Configure pins as AF pushpull */
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_Init(GPIOB, &GPIO_InitStructure);  
}

void USART_Configuration(void)                //´®¿Ú³õʼ»¯º¯Êý
{  
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable USART1 Peripheral clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
  /* USART1(PB6->TX, PB7->RX) Configuration(9600, 8, 1, N) */
        USART_InitStructure.USART_BaudRate = 9600;                //ÉèÖô®¿Ú²¨ÌØÂÊ
        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);                //ÅäÖÃÈë½á¹¹Ìå
  /* Enable USART1 Receive and Transmit interrupts */
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  /* Enable the USART1 interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

/*----------------------------------------------------------------------------*/
        USART_Cmd(USART1, ENABLE);                                                //ʹÄÜ´®¿Ú1
}

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Enixfaver + 1 谢谢
5
dongnanxibei| | 2015-12-30 21:25 | 只看该作者
mbed UART通讯

Uart(Universal Asynchronous Receiver/Transmitter)异步串口通讯是各类单片机中最古老又是最常用的通讯方式,在UART通讯过程中,我们需要使用3条信号线,即发送(RX),接收(TX)和地(GND),对于收发双方来说,RX和TX要交叉连接。由于这三条线中并不带时钟信号,所有在使用时必须约定数据的发送速度,即波特率;另外为了让接收方能够准确地识别出1个字符,还还需要在发送时添加起始位(1位)和停止位(1,1.5,2位)。由于UART通讯以字符为传输单位(一般是8个bit,但也可以是其它,如7个,9个),且字符的发送时间是不确定的(异步的),所以我们称它为异步串口通讯。UART串口通讯具有结构简单,实现方便的优点,但也有传输速度低的缺点。


在具体的应用中,UART串口有TTL电平的串口和RS232电平的串口类中,TTL电平是高电平为3.3V,低电平为0;而RS232是负逻辑电平,它定义+5~+12V为低电平,而-12~-5V为高电平,对于不加外部电路的单片机而言,它的UART输出都是TTL电平,相对RS232电平来说,通讯距离较短,而且容易受到干扰,但功耗较低,适合1米以内的短距离数据传输。下图是UART数据通讯过程中的时序图:

Uart串口通讯其实在前面的代码中已经用到过,标准C语言的printf函数也被重定义到串口输出上,方便用户的调试,对于mbed来说,它使用Serial对象来完成串口的数据收发,它提供的主要方法有:

类名
方法
用途
Serial
Serial(PinName tx, PinName rx, const char *name=NULL);
构造函数,把tx,rx设成Uart的输出输入管脚
void baud(int baudrate);
设置Uart的波特率,默认为9600
void format(int bits=8, Parity parity=SerialBase::None, int stop_bits=1);
设置Uart传输的格式,包括一个字长的位数、奇偶检验的方法、停止位的位数,默认为一个字长为8位,无奇偶检验,1位停止位
int readable();
返回Uart是否有数据到达
int writeable();
返回Uart是否还有空间进行数据发送
void attach(void (*fptr)(void), IrqType type=RxIrq);
设置Uart中断是需要执行的用户自定义函数
void set_flow_control(Flow type, PinName flow1=NC, PinName flow2=NC);
设置Uart的流控方法,其目标是提高数据发送的可靠性,流控方法有无流控,RTS流控,CTS流控,RTSCTS流控,后面两个常数为流控的管脚设置
int getc()
从Uart读取一个字符
int putc(int c);
向Uart发送一个字符
int printf(const char* format, ...)
格式化Uart的输出,参数等同标准C的printf
int scanf(const char* format, ...);
格式化Uart的输入,参数等同标准C的scanf




使用特权

评论回复
6
dongnanxibei| | 2015-12-30 21:26 | 只看该作者

在这里需要重点说明的是,并不是所有的管脚都能成为Uart管脚,只要被定义成Uart相关功能的GPIO管脚才行,具体来说,需要参考mbed每个平台实现的Serial_api.c文件,其中的相关代码入如下:

#define UART_NUM    4

static const PinMap PinMap_UART_TX[] = {

    {P0_0,  UART_3, 2},

    {P0_2,  UART_0, 1},

    {P0_10, UART_2, 1},

    {P0_15, UART_1, 1},

    {P0_25, UART_3, 3},

    {P2_0 , UART_1, 2},

    {P2_8 , UART_2, 2},

    {P4_28, UART_3, 3},

    {NC   , NC    , 0}

};

static const PinMap PinMap_UART_RX[] = {

    {P0_1 , UART_3, 2},

    {P0_3 , UART_0, 1},

    {P0_11, UART_2, 1},

    {P0_16, UART_1, 1},

    {P0_26, UART_3, 3},

    {P2_1 , UART_1, 2},

    {P2_9 , UART_2, 2},

    {P4_29, UART_3, 3},

    {NC   , NC    , 0}

};

static const PinMap PinMap_UART_RTS[] = {

    {P0_22, UART_1, 1},

    {P2_7,  UART_1, 2},

    {NC,    NC,     0}

};

static const PinMap PinMap_UART_CTS[] = {

    {P0_17, UART_1, 1},

    {P2_2,  UART_1, 2},

    {NC,    NC,     0}

};

这四个PinMap类型的定义就定义了可以用作Uart各类功能的管脚名称,其中的PinMap类型定义如下:

typedefstruct {

    PinNamepin;

    intperipheral;

    intfunction;


} PinMap;

其中的各个成员函数可以理解成管脚好、功能类型即UART、ADC、I2C等以及该功能对应GPIO的复用功能知识,如PinMap_UART_TX[]中的 {P0_0,  UART_3, 2}表示P0_0管脚可以用作UART3的TX管脚,它对应的功能序号为2;PinMap_UART_RX[]中的{P0_1 , UART_3, 2}表示P0_1管脚可以用作UART3的RX管脚,它对应的功能序号为2。如果你查找LPC1768的Datasheet,你可以发现下面的说明:


后面的I2C,SPI等的构造函数也是同样的原理。对于xbed LPC1768来说,它一共有4个UART口,分别是UART0,UART1,UART2,UART3,其中的UART0已经和CP2104相连,同时也用作printf的重定向输出,用户无法外接使用。


使用特权

评论回复
7
dongnanxibei| | 2015-12-30 21:27 | 只看该作者
  mbed Uart双向串行通讯应用

为了理解UART的通讯方法,我们先来输入下面的代码:

Serial pc(USBRX,USBTX);

DigitalOut led(LED1);

int main()

{

    while (1)

    {

        pc.putc(pc.getc());

        led=0;

        wait(0.1);

        led=1;

        wait(0.1);

    }


}

我们编译上载后运行你会发现xbed LPC1768 LED乱闪,这是mbed出错的指示方式,表示用户的程序在运行过程中出现了问题,这是因为我们把不能设定为tx的USBRX管脚设成了tx管脚,我们把USBRX、USBTX换个顺序后程序就运行正常了。

现在我们来审视一下这段代码,它的目的是回显用户的输入,并保持LED的变换,但实际上我们发现该程序在运行过程中有以下问题:

l  当用户没有字符输入时,LED灯并不会变化,程序处于等待状态;

l  当用户一次输入字符过多时,返回的字符会有丢失。

这些问题的产生是由mbed Serial API实现的原理决定的,在mbed中,getc()这一读取函数会一直等待直到读取到输入,所以当没有字符输入时LED灯不会变化;至于字符丢失是因为LPC1768的UART有16个自己的发送和接收队列,对于超过16个字节的数据必须等待mbed读取完了以后再进行处理,如果读取处理速度不够快的会数据就丢失了,而本代码中0.1秒才读一次,显然是不行的,如果我们把wait(0.1)都去掉,那就没问题了。

当然,我们也可以换种方式来使用UART,前面的代码是用户不断地去读取串口数据,也就是我们所说的轮询方式,这种方式效率是很低的,与其对应的是中断方式,即当串口有数据的时候主动通知程序,下面是改进后的代码,此时你会发现数据丢失的问题也没了:

Serial pc(USBTX,USBRX);

DigitalOut led(LED1);

void echouart()

{

    pc.putc(pc.getc());

}

int main()

{

    pc.attach(&echouart,SerialBase::RxIrq);

    while (1)

    {

        led=0;

        wait(0.1);

        led=1;

        wait(0.1);

    }


}

在Uart串口的双向通讯中,经常涉及到一个用户交互的问题,如当用户执行完一段代码后,经常会说请按任意键或特定键继续,这是,就相当于让程序一直等待,直到程序期待的字符出现,这在mbed中是很容易的,如下面的代码:

Serial pc(USBTX,USBRX);

DigitalOut led(LED1);

char username[100];

int userkey;

int main()

{

    pc.printf("Hello World,please enter you name to continue\r\n");

    pc.scanf("%s",username);

    pc.printf("You name is %s \r\n",username);

    while (pc.readable())

        pc.getc();

    while (1)

    {

        pc.printf("Hello World,please enter return to continue\r\n");

        userkey=pc.getc();

        if (userkey=='\r')

            break;

        else

            pc.printf("Wrong key,please enter return key to continue \r\n");

    }

    pc.printf("Right key,good bye \r\n");


}

         这里需要注意的是,我们额外添加了while (pc.readable())       pc.getc()这部分代码,其目标是为了防止前面的输入有可能没有被scanf读取完全,所以先把它清空再读取。

         考虑到串口操作涉及的大量是字符串操作,所以我们在必要时还可以使用C++的string类来简化字符串的处理,在利用string之前,必须要添加string的引用,即#include<string>,注意不是string.h,string的具体用法可以参见C++的手册,下面是一个简单的例子,用户可以尝试一下,如果做复杂的字符串查找替换操作,建议使用string类:

#include<string>

char username[100];

string str("You name is ");

int main()

{

    pc.printf("Hello World,please enter you name to continue\r\n");

    pc.scanf("%s",username);

    str=str.append(username);

    str=str.append(". \n");

    pc.printf(str.data());


}


使用特权

评论回复
8
dongnanxibei| | 2015-12-30 21:35 | 只看该作者
Serial(PinName tx, PinName rx, const char *name=NULL);
Serial pc(USBTX,USBRX);
那么上面第二个的TX、RX 是在哪儿指定?

使用特权

评论回复
9
狼牙0354| | 2015-12-31 08:39 | 只看该作者
1、检查硬件上是否有问题(通信电平是否匹配)
2、发送函数是否有问题
3、上位机配置是否与函数中的配置一致

初始化函数貌似没有问题(看的不是太仔细)

使用特权

评论回复
10
尤彼卡| | 2015-12-31 14:24 | 只看该作者
先查查硬件上是否有问题,程序上要注意时序

使用特权

评论回复
11
可可球| | 2015-12-31 16:29 | 只看该作者
UART串口有TTL电平的串口和RS232电平,TTL电平是高电平为3.3V,低电平为0

使用特权

评论回复
12
zhuotuzi| | 2015-12-31 17:29 | 只看该作者
这个系列官方提供的有例程没,就是去官网看看有没有什么cube开发包。

使用特权

评论回复
13
冰河w| | 2015-12-31 20:36 | 只看该作者
波特率是否设置的一致

使用特权

评论回复
14
FireRiver9| | 2015-12-31 20:54 | 只看该作者
检查一下时序是否正确

使用特权

评论回复
15
豆腐块| | 2015-12-31 21:19 | 只看该作者
仔细检查一下初始化函数吧,可能是初始化没配置号

使用特权

评论回复
16
Enixfaver|  楼主 | 2016-1-6 14:32 | 只看该作者
我后来查了下 硬件上的问题 有个孔焊接时被短路了 谢谢大家

使用特权

评论回复
17
Enixfaver|  楼主 | 2016-1-6 14:35 | 只看该作者
Huge2015 发表于 2015-12-30 17:41
同为新手,参考例子配置的串口,测试可用。

void GPIO_Configuration(void)

虽然不是软件的问题 还是谢谢了

使用特权

评论回复
18
买醉的显示器| | 2016-10-21 14:18 | 只看该作者
您的串口波特率设置为何是115200呢?

使用特权

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

本版积分规则

1

主题

4

帖子

0

粉丝