stm32之USART通信
任何USART通信,需要用到2个对外连接的引脚:RxD,TxD;
RxD是输入引脚,用于串行数据接收;
TxD是输出引脚,用于串行数据发送;
SCLK引脚:发生器时钟输出(同步模式下,异步模式下不需要)
在IrDA模式(红外模式)下需要下列引脚:
IrDA_RDI: 红外模式下的数据输入;
IrDA_TDO:红外模式下的数据输出;
调制解调模式下需要:
nCTS:清除发送;
nRTS:发送请求;
数据的接收/发送过程示意图:
异步串行通信协议需要定义以下5个内容:
1、起始位 2、数据位(8/9位,9位的话包含奇偶校验位,8位一字节)
3、奇偶校验位(第9位)
4、停止位(1、1.5、2位)
5、波特率设置(速度,波特率决定移位寄存器速度)
异步通信时,双方设置必须一致
;
USART用途:
芯片间的近距离通信:
芯片与pc机通信:
模块与模块之间远距离通信:借助RS485芯片-------can总线是在485上面发展起来的;
RS-485接口的最大传输距离可达3000米;
USART内部关于寄存器控制:
USART发送设置:
1、通过在USART_CR1寄存器上置位UE位来激活USART
2、设置USART_CR1的M位来定义字长;
3、设置USART_CR2中停止位的位数;
如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT),按多缓冲器通信中的描述配置DMA寄存器;
4、设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送;
5、利用USART_BRR寄存器选择要求的波特率;
6、把要发送的数据写进USART_DR寄存器(若数据发送完成由硬件清除);在只有一个缓冲器的情况下,重复步骤6;
1 #include "stm32f10x_gpio.h" 2 #include "stm32f10x_rcc.h" 3 4 #define GPIOA_ODR_A (GPIOA_BASE+0x0C) 5 #define GPIOA_IDR_A (GPIOA_BASE+0x08) 6 #define GPIOA_ODR_B (GPIOB_BASE+0x0C) 7 #define GPIOA_IDR_B (GPIOB_BASE+0x08) 8 #define GPIOA_ODR_C (GPIOC_BASE+0x0C) 9 #define GPIOA_IDR_C (GPIOC_BASE+0x08) 10 #define GPIOA_ODR_D (GPIOD_BASE+0x0C) 11 #define GPIOA_IDR_D (GPIOD_BASE+0x08) 12 #define GPIOA_ODR_E (GPIOE_BASE+0x0C) 13 #define GPIOA_IDR_E (GPIOE_BASE+0x08) 14 15 #define BitBand(Addr, BitNum) *((volatile unsigned long *)((Addr&0xF0000000)+0x2000000 +((Addr&0xfffff)<<5)+(BitNum<<2))) 16 #define PAout(n) BitBand(GPIOA_ODR_A, n) 17 #define PAin(n) BitBand(GPIOA_IDR_A, n) 18 19 /******************************************************************************* 20 * Function Name : RCC_Configuration 21 * Description : Configures the different system clocks. 22 * Input : None 23 * Output : None 24 * Return : None 25 *******************************************************************************/ 26 void RCC_Configuration(void) 27 { 28 /*---------------使用外部RC晶振----------*/ 29 RCC_DeInit(); //设置时钟为缺省值 30 RCC_HSEConfig(RCC_HSE_ON); //使能外部高速晶振 31 while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);//等待HSE准备就绪 32 33 // FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能指令预取 34 // FLASH_SetLatency(FLASH_Latency_2); //等待2个周期 35 36 RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK 37 RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK 38 RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2 39 RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 72MHZ 40 RCC_PLLCmd(ENABLE); //Enable PLLCLK 41 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait PLL is ready 42 43 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //SYSCLK = PLLCLK 44 while(RCC_GetSYSCLKSource()!= 0x08); //Wait PLLCLK as system clock 45 46 47 //---------打开相应外设时钟-------------------- 48 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能APB2外设的GPIOA的时钟 49 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟 50 } 51 52 void GPIO_Configuration(void) 53 { 54 GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量 55 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择PA.3 56 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ 57 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出模式为推挽输出 58 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA寄存器 59 60 61 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PA.10 62 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ 63 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//输入为浮空输入 64 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA寄存器 65 } 66 67 68 int main() 69 { 70 float div; 71 u16 M, F, BRR; 72 u32 Bound; 73 u8 data = 'A'; 74 //USART1模块的设置:UE使能、M位来定字长 、停止位的位数、 75 //TE位; BRR寄存器选择要求的波特率, 76 77 RCC_Configuration(); //打开系统时钟 78 GPIO_Configuration(); //引脚设置 79 USART1->CR1 |= (1<<13); 80 USART1->CR1 &= ~(1<<12); 81 USART1->CR2 &= ~(3<<12); 82 USART1->CR1 |=(1<<3); 83 //Tx / Rx 波特率 = fck/(16 *USARTDIV ) 84 //波特率=9600; fck=72M 85 //小数部分=0.75×16=12 = 0x 86 Bound = 9600; 87 div = (float)(72*1000*1000)/(Bound*16); 88 M = div; 89 F = (div-M)*16; 90 //拼接数据 91 BRR = (M<<4)+F; 92 USART1->BRR = BRR; 93 94 95 96 //发送字符‘A’到USART1的TXD 97 for(F=0;F<20;F++) 98 { 99 USART1->DR = data; 100 data++; 101 while((USART1->SR &(1<<6)) ==0 ) //等待发送完成才能再次发送 102 ; 103 } 104 105 return 0; 106 }
USART接收设置:
1、将USART_CR1寄存器的UE置1来激活USART.
2、编程USART_CR1的M位定义字长;
3、在USART_CR2中编写停止位的个数;
注意:如果需多缓冲通信,选择USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信所要求的配置DMA寄存器;
4、利用波特率寄存器USART_BRR选择希望的波特率;
5、设置USART_CR1的RE位,激活接收器,使它开始寻找起始位;
当一字符被接收到时:
RXNE位被置位,它表明移位寄存器的内容被转移到RDR.
如果RXNEIE位被设置,产生中断;
在接收期间如果检测到帧错误,噪音或者溢出错误,错误标志将被置起;