打印

STM32F103ZET6串口2通信不正常

[复制链接]
7659|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ab24656|  楼主 | 2011-8-11 20:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"  
#include "delay.h"
int main(void)
{   
u8 t;
u8 len;
// u16 times=0;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);      //延时初始化
uart_init(72,9600);  //串口初始化为9600
while(1)
{
  if(USART_RX_STA&0x80)
  {
         
   len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
   
   for(t=0;t<len;t++)
   {
    USART2->DR=USART_RX_BUF[t];
    while((USART2->SR&0X40)==0);//等待发送结束
   }
  
   USART_RX_STA=0;
  }
}  
}
#include <stm32f10x_lib.h>   
#include "sys.h"
   
//设置向量表偏移地址
//NVIC_VectTab:基址
//Offset:偏移量
//CHECK OK
//091207
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)  
{
   //检查参数合法性
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));   
SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//设置NVIC的向量表偏移寄存器
//用于标识向量表是在CODE区还是在RAM区
}
//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组
//CHECK OK
//091209
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)  
{
u32 temp,temp1;   
temp1=(~NVIC_Group)&0x07;//取后三位
temp1<<=8;
temp=SCB->AIRCR;  //读取先前的设置
temp&=0X0000F8FF; //清空先前分组
temp|=0X05FA0000; //写入钥匙
temp|=temp1;   
SCB->AIRCR=temp;  //设置分组               
}
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority       :响应优先级
//NVIC_Channel           :中断编号
//NVIC_Group             :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
//CHECK OK
//100329
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)  
{
u32 temp;
u8 IPRADDR=NVIC_Channel/4;  //每组只能存4个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4;    //得到偏移的确切位置
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);   
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位(要清除的话,相反操作就OK)
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   
NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级和抢断优先级                  
}
//外部中断配置函数
//只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
//参数:GPIOx:0~6,代表GPIOA~G;BITx:需要使能的位;TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发
//该函数一次只能配置1个IO口,多个IO口,需多次调用
//该函数会自动开启对应中断,以及屏蔽线   
//待测试...
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
{
u8 EXTADDR;
u8 EXTOFFSET;
EXTADDR=BITx/4;//得到中断寄存器组的编号
EXTOFFSET=(BITx%4)*4;
RCC->APB2ENR|=0x01;//使能io复用时钟
AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);//清除原来设置!!!
AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;//EXTI.BITx映射到GPIOx.BITx

//自动设置
EXTI->IMR|=1<<BITx;//  开启line BITx上的中断
//EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
  if(TRIM&0x01)EXTI->FTSR|=1<<BITx;//line BITx上事件下降沿触发
if(TRIM&0x02)EXTI->RTSR|=1<<BITx;//line BITx上事件上升降沿触发
}

//不能在这里执行所有外设复位!否则至少引起串口不工作.      
//把所有时钟寄存器复位
//CHECK OK
//091209
void MYRCC_DeInit(void)
{                    
RCC->APB1RSTR = 0x00000000;//复位结束   
RCC->APB2RSTR = 0x00000000;
   
   RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.   
   RCC->APB2ENR = 0x00000000; //外设时钟关闭.      
   RCC->APB1ENR = 0x00000000;   
RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                  
RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]      
RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP      
RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
RCC->CIR = 0x00000000;     //关闭所有中断
//配置向量表      
#ifdef  VECT_TAB_RAM
MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else   
MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
//CHECK OK
//091209
__asm void WFI_SET(void)
{
WFI;   
}
//进入待机模式  
//check ok
//091202
void Sys_Standby(void)
{
SCB->SCR|=1<<2;//使能SLEEPDEEP位 (SYS->CTRL)   
   RCC->APB1ENR|=1<<28;     //使能电源时钟     
  PWR->CSR|=1<<8;          //设置WKUP用于唤醒
PWR->CR|=1<<2;           //清除Wake-up 标志
PWR->CR|=1<<1;           //PDDS置位   
WFI_SET();     //执行WFI指令   
}   
//后备寄存器写入操作
//reg:寄存器编号
//reg:要写入的数值
////check ok
////091202
//void BKP_Write(u8 reg,u16 dat)
//{
//  RCC->APB1ENR|=1<<28;     //使能电源时钟     
// RCC->APB1ENR|=1<<27;     //使能备份时钟     
// PWR->CR|=1<<8;           //取消备份区写保护
// switch(reg)
// {
//  case 1:
//   BKP->DR1=dat;
//   break;
//  case 2:
//   BKP->DR2=dat;
//   break;
//  case 3:
//   BKP->DR3=dat;
//   break;
//  case 4:
//   BKP->DR4=dat;
//   break;
//  case 5:
//   BKP->DR5=dat;
//   break;
//  case 6:
//   BKP->DR6=dat;
//   break;
//  case 7:
//   BKP->DR7=dat;
//   break;
//  case 8:
//   BKP->DR8=dat;
//   break;
//  case 9:
//   BKP->DR9=dat;
//   break;
//  case 10:
//   BKP->DR10=dat;
//   break;
// }
//}     
//系统软复位
//CHECK OK
//091209
void Sys_Soft_Reset(void)
{   
SCB->AIRCR =0X05FA0000|(u32)0x04;   
}
//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
//CHECK OK
//100818   
void JTAG_Set(u8 mode)
{
u32 temp;
temp=mode;
temp<<=25;
RCC->APB2ENR|=1<<0;     //开启辅助时钟   
AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
AFIO->MAPR|=temp;       //设置jtag模式
}
//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16
//CHECK OK
//091209
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;   
MYRCC_DeInit();    //复位并配置向量表
RCC->CR|=0x00010000;  //外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等待外部时钟就绪
RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2个单位
RCC->CFGR|=PLL<<18;   //设置PLL值 2~16
RCC->CFGR|=1<<16;   //PLLSRC ON
FLASH->ACR|=0x32;   //FLASH 2个延时周期
RCC->CR|=0x01000000;  //PLLON
while(!(RCC->CR>>25));//等待PLL锁定
RCC->CFGR|=0x00000002;//PLL作为系统时钟  
while(temp!=0x02)     //等待PLL作为系统时钟设置成功
{   
  temp=RCC->CFGR>>2;
  temp&=0x03;
}   
}      
#include "sys.h"
#include "usart.h"
//加入以下代码,支持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((USART2->SR&0X40)==0);//循环发送,直到发送完毕   
USART2->DR = (u8) ch;      
return ch;
}
#endif
//end
//////////////////////////////////////////////////////////////////
#ifdef EN_USART2_RX   //如果使能了接收
//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   
u8 USART_RX_BUF[5];     //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0;       //接收状态标记   
void USART2_IRQHandler(void)
{
u8 res;
// USART_RX_BUF[0]=USART2->DR;

   
if(USART2->SR&(1<<5))//接收到数据
{  
  res=USART2->DR;
  if((USART_RX_STA&0x80)==0)//接收未完成
  {
   if(USART_RX_STA&0x40)//接收到了0x0d
   {
    if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    else USART_RX_STA|=0x80; //接收完成了
   }else //还没收到0X0D
   {
    if(res==0x0d)USART_RX_STA|=0x40;
    else
    {
     USART_RX_BUF[USART_RX_STA&0X3F]=res;
     USART_RX_STA++;
     if(USART_RX_STA>5)USART_RX_STA=0;//接收数据错误,重新开始接收   
    }   
   }
  }                  
}              
}
#endif           
//初始化IO 串口2
//pclk2:PCLK2时钟频率(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->APB1ENR|=1<<17;  //使能串口时钟
GPIOA->CRL&=0XFFFF00FF;
GPIOA->CRL|=0X00008B00;//IO状态设置
   
RCC->APB1RSTR|=1<<17;   //复位串口2
RCC->APB1RSTR&=~(1<<17);//停止复位        
//波特率设置
  USART2->BRR=mantissa; // 波特率设置  
USART2->CR1|=0X200C;  //1位停止,无校验位.

#ifdef EN_USART2_RX    //如果使能了接收
//使能接收中断
USART2->CR1|=1<<8;    //PE中断使能
USART2->CR1|=1<<5;    //接收缓冲区非空中断使能      
MY_NVIC_Init(3,3,USART2_IRQChannel,2);//组2,最低优先级
#endif
}
#include <stm32f10x_lib.h>
#include "delay.h"

static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
fac_us=SYSCLK/8;      
fac_ms=(u16)fac_us*1000;
}            
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{         
u32 temp;     
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00;           //清空计数器
SysTick->CTRL=0x01 ;          //开始倒数  
do
{
  temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
SysTick->CTRL=0x00;       //关闭计数器
SysTick->VAL =0X00;       //清空计数器        
}   
//延时nus
//nus为要延时的us数.                 
void delay_us(u32 nus)
{  
u32 temp;      
SysTick->LOAD=nus*fac_us; //时间加载      
SysTick->VAL=0x00;        //清空计数器
SysTick->CTRL=0x01 ;      //开始倒数   
do
{
  temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
SysTick->CTRL=0x00;       //关闭计数器
SysTick->VAL =0X00;       //清空计数器  
}
沙发
ab24656|  楼主 | 2011-8-11 21:01 | 只看该作者
源程序[local]1[/local]

使用特权

评论回复
板凳
lfzwb| | 2014-9-11 12:24 | 只看该作者
我也是这么写的,也是串口2没反应

使用特权

评论回复
地板
lfzwb| | 2014-9-11 12:24 | 只看该作者
楼主问题解决了吗

使用特权

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

本版积分规则

2

主题

8

帖子

0

粉丝