高级会员

- 积分
- 598
- 金钱
- 598
- 注册时间
- 2014-4-14
- 在线时间
- 76 小时
|
发表于 2016-9-5 13:55:15
|
显示全部楼层
本帖最后由 GS1101923161 于 2016-9-5 16:31 编辑
不懂你这置0是啥意思,送你比较通用的串口程序,支持普通的串口收发、支持485、支持库版本和寄存器版本的选择性编译,
usart1.c文件如下
[mw_shl_code=c,true]#include <string.h>
#include "usart1.h"
#include "delay.h"
/* 最大缓存 */
#define MAXRECV USART1_BUFF
static u8 RX_BUFF[MAXRECV]={0}; //接收缓冲
static u32 RX_SIZ=0; //接收到的数据长度
#if (USART1_485_EN == 1)
#define RS485_TX_EN PAout(8) //485模式控制.0,接收;1,发送.
#endif
/*********************************************************
* @function usart1_Configuration
* @role USART1串口初始化
* @input bound:波特率
* @output None
* @return None
********************************************************/
#if USART1_SYS
void usart1_Configuration(u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(72*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
#if (USART1_MAP_EN == 0)
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;//IO状态设置
GPIOA->CRH|=0X000008B0;//IO状态设置
#else
RCC->APB2ENR|=((1<<0)|(1<<3)); //使能PORTB\AFIO口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
AFIO->MAPR|=1<<2; //使能端口重映射
GPIOB->CRL&=0X00FFFFFF;//IO状态设置
GPIOB->CRL|=0X8B000000;//IO状态设置
#endif
#if USART1_485_EN
/* 485的RE脚设置,根据实际情况在这里添加寄存器模式下的初始化代码*/
#endif
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
//如果使能了接收
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
}
#else
void usart1_Configuration(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#if (USART1_MAP_EN == 0)
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA9 TX
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);
//PA10 RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#else
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);//开启端口B和复用功能时钟
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);//使能端口重映射
//uart 的GPIO重映射管脚初始化
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//悬空输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
#endif
#if (USART1_485_EN == 1)
//RE PA.8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //输入输出控制IO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据长度
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); //初始化串口
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级3级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
USART_Cmd(USART1, ENABLE); //使能串口
USART_ClearFlag(USART1, USART_FLAG_TC); // 清标志
RX_SIZ = 0;
#if (USART1_485_EN == 1)
RS485_TX_EN=0; //默认为接收模式
#endif
}
#endif
/*********************************************************
* @function USART1_IRQHandler
* @role 串口接收中断
* @input None
* @output None
* @return None
********************************************************/
void USART1_IRQHandler(void)
{
u8 buff = 0;
#if USART1_SYS
if(USART1->SR&(1<<5))//接收到数据
{
if(RX_SIZ < MAXRECV){
buff = USART1->DR;//记录接收到的值
if(buff || RX_SIZ){
RX_BUFF[RX_SIZ++] = buff;
}
}
}
#else
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收到数据
{
if(RX_SIZ < MAXRECV){
buff = USART_ReceiveData(USART1);//记录接收到的值
if(buff || RX_SIZ){
RX_BUFF[RX_SIZ++] = buff;
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志.
}
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)//溢出?
{
USART_ClearFlag(USART1,USART_FLAG_ORE);//读SR
USART_ReceiveData(USART1);//读DR?
}
#endif
}
/*********************************************************
* @function usart1_Send
* @role 发送len个字节.
* @input 要发送的数据与长度,
(为了和本代码的接收匹配,这里建议不要超过 MAXRECV 个字节)
* @output None
* @return None
********************************************************/
void usart1_Send(u8 *buf,u32 len)
{
u32 t;
#if (USART1_485_EN == 1)
RS485_TX_EN=1;
#endif
#if USART1_SYS
for(t=0;t<len;t++)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) buf[t];
}
while((USART1->SR&0X40)==0);//等待发送结束
#else
for(t=0;t<len;t++) //循环发送数据
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1,buf[t]);
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET){//发送一个字符完成产生中断
USART_ClearITPendingBit(USART1 ,USART_IT_TXE);//清发送中断
}
#endif
#if (USART1_485_EN == 1)
RS485_TX_EN=0;
#endif
}
/*********************************************************
* @function usart1_Receive
* @role RS232查询接收到的数据
* @input buf:接收缓存首地址,与缓存长度
* @output None
* @return 接收的数据长度
********************************************************/
u32 usart1_Receive(u8 *buf, u32 buflen)
{
u32 rxlen=RX_SIZ;
u32 i=0;
u32 ret = 0; //默认为0
delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
if(rxlen==RX_SIZ && rxlen)//接收到了数据,且接收完成了
{
for(i=0;(i < rxlen) && (i < (buflen - 1));i++)
{
buf=RX_BUFF;
RX_BUFF = 0;
}
buf='\0';
ret=i; //记录本次数据长度
RX_SIZ=0; //清零
}
return ret;
}
/*********************************************************
* @function usart1_FreeBuff
* @role 清空缓存中的数据
* @input None
* @output None
* @return None
********************************************************/
void usart1_FreeBuff(void)
{
int rxlen=RX_SIZ;
int i=0;
delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
while(rxlen)
{
if(rxlen==RX_SIZ && rxlen)//接收到了数据,且接收完成了
{
for(i=0;(i<rxlen) && (i < (MAXRECV-1)) ;i++){
RX_BUFF = 0;
}
RX_SIZ=0; //清零
}
delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
rxlen=RX_SIZ;
}
}
[/mw_shl_code]
usaert1.h文件如下[mw_shl_code=c,true]
#ifndef __USART1_H_
#define __USART1_H_
#include "sys.h"
#define USART1_SYS 1 //设置编译版本,0是库版本,1是寄存器版本
#define USART1_BUFF 200 //接收数据缓存
#define USART1_485_EN 0 //1 开启485功能,0 关闭485功能
#define USART1_MAP_EN 0 //1 开启重定向功能,0关闭重定向功能
void usart1_Configuration(u32 bound);
void usart1_Send(u8 *buf,u32 len);
u32 usart1_Receive(u8 *buf, u32 buflen);
void usart1_FreeBuff(void);
#endif
[/mw_shl_code]
其他的几个串口都可以参考这个模式写。
|
|