OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3008|回复: 5

为什么我用串口四发数据到串口一,串口四会有接收到乱码,串口一接收的数据完整的,还有为什么串口四用不了myprint函数,代码...

[复制链接]

2

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-3-31
在线时间
9 小时
发表于 2020-5-21 10:12:43 | 显示全部楼层 |阅读模式
6金钱
(1)#include "usart.h"
#include "sys.h"
usart.c  文件
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h"                                        //ucos 使用          
#endif
////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//串口1初始化                  
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/8/18
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
////////////////////////////////////////////////////////////////////////////////           


////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB          
#if 1
#pragma import(__use_no_semihosting)            
//标准库需要的支持函数                 
struct __FILE
{
        int handle;
        /* Whatever you require here. If the only file you are using is */
        /* standard output using printf() for debugging, no file handling */
        /* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
_sys_exit(int x)
{
        x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{      
        while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
        USART1->DR = (u8) ch;      
        return ch;
}
#endif
//end
#if EN_USART1_RX
static void TIM5_init(u16 ms);
#endif
//////////////////////////////////////////////////////////////////
#if EN_USART1_RX   //如果使能了接收  做了修改
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,        接收完成标志
//bit14,        接收到0x0d
//bit13~0,        接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记          
void USART1_IRQHandler(void)//串口一中断
{
        u8 res;       
        if(USART1->SR&(1<<5))//接收到数据
        {         
                res=USART1->DR;
                TIM5->CNT = 0;
                if((USART_RX_STA&0x8000) == 0)
                {
                        TIM5->CR1 |= 0x01;
                        USART_RX_BUF[USART_RX_STA&0x3FFF] = res;
                        USART_RX_STA++;
                        if(USART_RX_STA > (UART3_RX_BUF_MAX        -1))
                        {
                                USART_RX_STA = 0;
                        }
                }
        }
}
static void TIM5_init(u16 ms)
{
        RCC->APB1ENR |= 1<<3;           //使能TIM5时钟
    TIM5->ARR = ms*10 - 1;          //ms*10次计数后溢出(7200分频刚好ms毫秒后溢出一次)
    TIM5->SC = 7200-1;             //7200分频              
    TIM5->DIER |= 1<<0;             //使能TIM5更新中断
    TIM5->CR1 |= 0x01;              //启动TIM5
    MY_NVIC_Init(2,3,TIM5_IRQn,2);  //次高抢占优先级,最低响应优先级
}

void TIM5_IRQHandler(void)
{
        if(TIM5->SR & 0x0001)           //计时溢出
    {
                USART_RX_STA |= 0x8000;
                USART_RX_BUF[USART_RX_STA&0x3FFF] = '\0';
                TIM5->CR1 &= ~(0x01);                //disable TIM5
    }
    TIM5->SR &= ~(1<<0);            //清除中断标志位
}

#endif               

//初始化IO 串口1
//pclk2CLK2时钟频率(Mhz)
//bound:波特率
//CHECK OK
//091209
void uart_init(u32 pclk2,u32 bound)
{           
        float temp;
        u16 mantissa;
        u16 fraction;          
        temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分
        fraction=(temp-mantissa)*16; //得到小数部分         
    mantissa<<=4;
        mantissa+=fraction;
        RCC->APB2ENR|=1<<2;   //使能PORTA口时钟  
        RCC->APB2ENR|=1<<14;  //使能串口时钟
        GPIOA->CRH&=0XFFFFF00F;//IO状态设置
        GPIOA->CRH|=0X000008B0;//IO状态设置
                  
        RCC->APB2RSTR|=1<<14;   //复位串口1
        RCC->APB2RSTR&=~(1<<14);//停止复位                     
        //波特率设置
        USART1->BRR=mantissa; // 波特率设置         
        USART1->CR1|=0X200C;  //1位停止,无校验位.
#if EN_USART1_RX                  //如果使能了接收
        //使能接收中断
        USART1->CR1|=1<<8;    //PE中断使能
        USART1->CR1|=1<<5;    //接收缓冲区非空中断使能       
        TIM5_init(10);
        MY_NVIC_Init(2,1,USART1_IRQn,2);//组2
#endif
}

//UART1 send len byte data from buffer buf
static void uart1SendData(const u8* buf, u16 len)
{
        while(len)
        {
                while((USART1->SR&0x40) == 0)
                ;
                USART1->DR = *buf;
                buf++;
                len--;
        }
}


//-----------------------------------------------------------
#if EN_UART3_RX
static void TIM4_init(u16 ms);
#endif

//初始化IO 串口3
//pclk1CLK1时钟频率(Mhz)
//bound:波特率
void uart3_init(u32 pclk1,u32 bound)
{           
        float temp;
        u16 mantissa;
        u16 fraction;          
        temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分
        fraction=(temp-mantissa)*16; //得到小数部分         
    mantissa<<=4;
        mantissa+=fraction;
        RCC->APB2ENR|=1<<3;   //使能PORTB口时钟  
        RCC->APB1ENR|=1<<18;  //使能串口时钟
        GPIOB->CRH&=0XFFFF00FF;//IO状态设置
        GPIOB->CRH|=0X00008B00;//IO状态设置
                  
        RCC->APB1RSTR|=1<<18;   //复位串口3
        RCC->APB1RSTR&=~(1<<18);//停止复位                     
        //波特率设置
        USART3->BRR=mantissa; // 波特率设置         
        USART3->CR1|=0X200C;  //1位停止,无校验位.
#if EN_UART3_RX                  //如果使能了接收
        //使能接收中断
        USART3->CR1|=1<<8;    //PE中断使能
        USART3->CR1|=1<<5;    //接收缓冲区非空中断使能         
        TIM4_init(10);
        MY_NVIC_Init(1,1,USART3_IRQn,2);//最高抢占优先级,最高响应优先级
        clearUart3Status();
#endif
}

//UART3 send len byte data from buffer buf
static void uart3SendData(const u8* buf, u16 len)
{
        while(len)
        {
                while((USART3->SR&0x40) == 0)
                ;
                USART3->DR = *buf;
                buf++;
                len--;
        }
}

//串口3发送字符串
void uart3SendStr(const char *str)
{
        char* s = (char*)str;
        while(*s)
        {
                while((USART3->SR&0X40)==0);//循环发送,直到发送完毕  
                USART3->DR = *s;
                s++;
        }   
}

#if EN_UART3_RX
u8 UART3_RX_BUF[UART3_RX_BUF_MAX];
u16 UART3_RX_STA = 0;

void USART3_IRQHandler(void)
{
        u8 dat;
        if(USART3->SR & (1<<5))
        {
                dat = USART3->DR;
                TIM4->CNT = 0;
                if((UART3_RX_STA&0x8000) == 0)
                {
                        TIM4->CR1 |= 0x01;
                        UART3_RX_BUF[UART3_RX_STA&0x3FFF] = dat;
                        UART3_RX_STA++;
                        if(UART3_RX_STA > (UART3_RX_BUF_MAX-1))
                        {
                                UART3_RX_STA = 0;
                        }
                }
        }
}

static void TIM4_init(u16 ms)
{
        RCC->APB1ENR |= 1<<2;           //使能TIM4时钟
    TIM4->ARR = ms*10 - 1;          //ms*10次计数后溢出(7200分频刚好ms毫秒后溢出一次)
    TIM4->SC = 7200-1;             //7200分频              
    TIM4->DIER |= 1<<0;             //使能TIM4更新中断
    TIM4->CR1 |= 0x01;              //启动TIM4
    MY_NVIC_Init(2,3,TIM4_IRQn,2);  //次高抢占优先级,最低响应优先级
}

void TIM4_IRQHandler(void)
{
        if(TIM4->SR & 0x0001)           //计时溢出
    {
                UART3_RX_STA |= 0x8000;
                UART3_RX_BUF[UART3_RX_STA&0x3FFF] = '\0';
                TIM4->CR1 &= ~(0x01);                //disable TIM4
    }
    TIM4->SR &= ~(1<<0);            //清除中断标志位
}

#endif

//--------------------------------------------------------

#if EN_UART4_RX   //如果使能了接收

//串口4中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误          
u8 UART4_RX_BUF[USART_REC_LEN ];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,        接收完成标志
//bit14,        接收到0x0d
//bit13~0,        接收到的有效字节数目
u16 UART4_RX_STA=0;       //接收状态标记          

void UART4_IRQHandler(void)  
{
        u8 res;
        if(UART4->SR&(1<<5))//接收到数据
        {         
                res=UART4->DR;
                if((UART4_RX_STA&0x8000)==0)//接收未完成
                {       
                        if(UART4_RX_STA&0x4000)//接收到了0x0d
                        {
                                if(res!=0x0a)UART4_RX_STA=0;//接收错误,重新开始0a:"\r"
                                else UART4_RX_STA|=0x8000;        //接收完成了
                        }else //还没收到0X0D
                        {       
                                if(res==0x0d)UART4_RX_STA|=0x4000;
                                else
                                {
                                        UART4_RX_BUF[UART4_RX_STA&0X3FFF]=res;
                                        UART4_RX_STA++;
                                        if(UART4_RX_STA>(UART3_RX_BUF_MAX -1))
                                        UART4_RX_STA=0;//接收数据错误,重新开始接收          
                                }                 
                        }
                }                                                                                                
        }
}
#endif       
//--------------------------------------------------------
//初始化IO 串口4
//pclk1CLK1时钟频率(Mhz)
//bound:波特率
void uart4_init(u32 pclk1,u32 bound)
{           
        float temp;
        u16 mantissa;
        u16 fraction;          
        temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分
        fraction=(temp-mantissa)*16; //得到小数部分         
    mantissa<<=4;
        mantissa+=fraction;
        RCC->APB2ENR|=1<<4;   //使能PORTC口时钟  
        RCC->APB1ENR|=1<<19;  //使能串口时钟
        GPIOC->CRH&=0XFFFF00FF;//IO状态设置
        GPIOC->CRH|=0X00008B00;//IO状态设置
                  
        RCC->APB1RSTR|=1<<19;   //复位串口4
        RCC->APB1RSTR&=~(1<<19);//停止复位                     
        //波特率设置
        UART4->BRR=mantissa; // 波特率设置         
        UART4->CR1|=0X200C;  //1位停止,无校验位.
#if EN_UART4_RX                  //如果使能了接收
        //使能接收中断
        UART4->CR1|=1<<8;    //PE中断使能
        UART4->CR1|=1<<5;    //接收缓冲区非空中断使能         
        //TIM4_init(10);
        MY_NVIC_Init(1,1,UART4_IRQn,2);//最高抢占优先级,最高响应优先级
        clearUart4Status();
#endif
}

//UART3 send len byte data from buffer buf
static void uart4SendData(const u8* buf, u16 len)
{
        while(len)
        {
                while((UART4->SR&0x40) == 0)
                ;
                UART4->DR = *buf;
                buf++;
                len--;
        }
}

//--------------------------------------------------------
//串口X发送len个字节
//@param uartX:        使用哪个串口发送
//@param buf:        待发送的缓冲区的指针
//@param len:        发送长度
void uartXSendData(u8 uartX, const u8* buf, u16 len)
{
        switch(uartX)
        {
                case 1:
                        uart1SendData(buf, len);
                        break;
                case 3:
                        uart3SendData(buf, len);
                        break;
                 case 4:
                        uart4SendData(buf, len);
                        break;
                default:
                        break;
        }
}

void myPrintf(u8 uartX, const char* fmt, ...)
{
        #define TEMP_BUF_MAX        200
        char temp[TEMP_BUF_MAX];
        char *buf = NULL;
        u16 cnt = 0;       
       
        va_list ap;                                                //可变参数列表,即三个句点...
        buf = temp;
        __va_start(ap, fmt);                        //__va_start(可变参数列表...,可变参数列表...的前一个参数)
        cnt = vsprintf(buf, fmt, ap);        //格式化后的字符串长度,包括\0 = vsprintf(格式化后字符串的存放缓冲区指针,待格式的字符串的指针,可变参数列表...)
        __va_end(ap);                                        //与__va_start()配对使用,释放可变参数列表
        uartXSendData(uartX, (const u8*)buf, cnt);
}
(2)usart.h 文件
#ifndef __USART_H
#define __USART_H
#include "sys.h"
#include "stdio.h"         
#include "stdarg.h"
////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//串口1初始化                  
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/8/18
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
////////////////////////////////////////////////////////////////////////////////        
#define USART_REC_LEN            200         //定义最大接收字节数 200
#define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
#define EN_UART3_RX                                1                //true: enable UART3 receive;        false: disable UART3 receive
#define EN_UART4_RX                                1
#define UART3_RX_BUF_MAX                1024        //max length of UART3 receive buffer


extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA;                         //接收状态标记         

extern u8 UART3_RX_BUF[UART3_RX_BUF_MAX];
extern u16 UART3_RX_STA;

extern u8 UART4_RX_BUF[USART_REC_LEN ];     //接收缓冲,最大USART_REC_LEN个字节.
extern u16 UART4_RX_STA;       //接收状态标记

void uart_init(u32 pclk2,u32 bound);
void uart3_init(u32 pclk1,u32 bound);
void uart4_init(u32 pclk1,u32 bound);
void uart3SendStr(const char *str);
#define didUart3DataCome()                (UART3_RX_STA & 0x8000)
#define clearUart3Status()                (UART3_RX_STA=0)
#define getUart3DataLen()                (UART3_RX_STA & 0x3FFF)
#define clearUart4Status()                (UART4_RX_STA=0)
void myPrintf(u8 uartX, const char* fmt, ...);

#endif          
  (3)main.c 文件
include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
        u8 len,t;
        Stm32_Clock_Init(9); //系统时钟设置
        delay_init(72); //延时函数初始化
        uart_init(72,115200);  //串口1初始化
        uart4_init(36,115200); //串口4初始化
       
        myPrintf(1,"AT+RST\r\n");//给WIFI模块复位一下
        delay_ms(1000);
  delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
  delay_ms(1000);
  myPrintf(1,"AT+CIPMUX=0\r\n");//设置为单连接模式
        delay_ms(1000);
        myPrintf(1,"AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n");//连接onenet HTTP服务器183.230.40.33/80
        delay_ms(1000);
        myPrintf(1, "AT+CIPMODE=1\r\n");//开启透传模式
        delay_ms(1000);
        myPrintf(1,"AT+CIPSEND\r\n");//数据开始透传
        delay_ms(1000);
        delay_ms(500);
        myPrintf(4,"AT+RST\r\n");//给WIFI模块复位一下
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        myPrintf(4,"AT+CIPMUX=1\r\n");//开启多连接模式
        delay_ms(1000);LED=1;//LED灭
        myPrintf(4,"AT+CIPSERVER=1,8089\r\n");//开启服务器模式
        delay_ms(1000);
       
                while(1)
                //串口4发送和接收数据       
                {       
                       
                if(UART4_RX_STA&0x8000)
                {
                        myPrintf(1,(const char*)UART4_RX_BUF);               
                        myPrintf(1,"\r\n");
                        UART4_RX_STA=0;
                }
        }
}

















正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

62

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2020-5-3
在线时间
0 小时
发表于 2020-5-21 10:12:45 | 显示全部楼层
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-5-22 01:11:08 | 显示全部楼层
1, 串口4和电脑通信正常么?
2, 串口1和电脑通信正常么?
3, printf用不了, 仿真找问题。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-3-31
在线时间
9 小时
 楼主| 发表于 2020-5-22 18:48:25 | 显示全部楼层
正点原子 发表于 2020-5-22 01:11
1, 串口4和电脑通信正常么?
2, 串口1和电脑通信正常么?
3, printf用不了, 仿真找问题。

串口四跟电脑通信没问题
串口一也没问题
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-3-31
在线时间
9 小时
 楼主| 发表于 2020-5-22 18:49:19 | 显示全部楼层
LJQ2020 发表于 2020-5-22 18:48
串口四跟电脑通信没问题
串口一也没问题

你看看我的代码有问题么,用的是原子的历程
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-5-23 01:17:57 | 显示全部楼层
LJQ2020 发表于 2020-5-22 18:49
你看看我的代码有问题么,用的是原子的历程

仿真看看
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-28 14:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表