1.同步串行通信
同步通信发送端和接收端必须用
共同的时钟源
才能保持它们之间的准确同步。同步传输时,每个字
符没有起始位和停止位,它不是用起始位来标志字符的开始,而是用一串特定的二进制序列,称为
同步字符,去通知接收器串行数据的第一位何时到达。然后,串行数据信息以连续的形式发送,每
个时钟周期发送1位数据。接收器搜索到同步字符后,才开始接收数据位。因此,同步传输时数据成
批连续发送,信息字符间不留空隙,它严格按照约定的速率发送和接收。(I2C,SPi)
2.异步串行通信
异步串行通信是指串口的发送与接收设备使用
各自的时钟
控制数据的发送和接收过程,以字符为数
据传输单位,字符之间可以有间隔。需要开始位和停止位确定发送数据的开始和结束。为使双方的
收发协调,要求发送和接收设备的串口工作时钟频率要尽可能一致.
3.常见通信协议
4. 串口电路连接
5.串口通信数据帧格式
波特率 一般是115200
6.波特率
7.波特率计算
8.串口编程(初始化)
9.串口编程(收发数据)
代码:
#include "myusart.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_gpio.h"
#include "stdio.h"
u8 USART_RX_BUF[USART_REC_LEN];
u16 USART_RX_STA = 0; //接受完成的标志
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x=x;
}
int fputc(int ch,FILE *f)
{
#if 0
while( (USART1->SR&(1<<6))==0 ); //发送未完成等待
USART1->DR = (unsigned char)ch; //发送完成,那么可以向DR写入下一个待发送的数据
return ch;
#else
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(unsigned char)ch);
return ch;
#endif
}
int fgetc(FILE *f)
{
#if 0
while((USART1->SR&(1<<5)) == 0); //数据寄存器非空(即:接收到数据),那么跳出循环,否则一直等待
return((int)(USART1->DR&0xff)); //接收完成,读取数据。
#else
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
return((int)(USART_ReceiveData(USART1)));
#endif
}
void myusart_init(int usart_btl)
{
//第一步:准备三个结构体
USART_InitTypeDef USART_InitStruct; // 串口通信
NVIC_InitTypeDef NVIC_InitStruct ; // 中断寄存器NVIC
GPIO_InitTypeDef GPIO_InitStruct; //GPIO设置结构体
//第二步: 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //GPIO口时钟使能
//第三步: 设置端口复用
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);
//把A组中的10引脚设置成串口1模式(复用)
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);
//
//第四步: 设置GPIO口的模式 (PA9 --TXD PA10 ---RXD)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF ; //复用功能
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA ,&GPIO_InitStruct);
GPIO_SetBits(GPIOA,GPIO_Pin_9);
/*GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init( GPIOA ,&GPIO_InitStruct);*/
// 第五步: 设置usart寄存器
USART_InitStruct.USART_BaudRate = usart_btl; // 波特率
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流
USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //允许接受和发送
USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位(无)
USART_InitStruct.USART_StopBits = USART_StopBits_1; //停止位 (1位)
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 字长 (8位)
USART_Init(USART1,&USART_InitStruct);
//第六步: 设置中断寄存器
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; // 中断号
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //终端号使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 响应优先级
NVIC_Init(&NVIC_InitStruct);
//第七步: 设置接收中断使能 设置串口使能
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收数据中断
USART_Cmd(USART1,ENABLE);
}
//发送数据 aabcdef\r\n
//串口1中断服务程序
u8 count = 0;
void USART1_IRQHandler(void) /串口接收数据的中断
{
u8 Res;
//接收中断(接收到的数据必须是0x0d 0x0a结尾)
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d 0100 0000 0000 0000
{
if(Res!='\n')USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到‘\r’
{
if(Res=='\r')USART_RX_STA|=0x4000; //USART_RX_STA = 1100 0000 0000 0000
else //USART_RX_BUF[0] = 'd'; USART_RX_BUF[1] = 'a';.. USART_RX_BUF[4] = 'y'
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; // danny\r\n
USART_RX_STA++;
//接收数据错误,重新开始接收
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
}
}
}
}
}
//进行串口通信,当用户发送01+02 串口接受到后 发送03 给到pc
/*
//main.c
SysTick_init(168);
//中断分组
u16 len = 0;
int i = 0;
SysTick_init(168);//初始化延时函数
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
myusart_init(115200);
while(1)
{
//数据接收完成
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
for(i=0;i<len;i++)
{
USART_SendData(USART1, USART_RX_BUF[i]);
//等待发送结束
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
}
if(len == 5)
{
if(USART_RX_BUF[2]==43)
{
int a1=((int)(USART_RX_BUF[0] -48)*10 )+ (int)(USART_RX_BUF[1] -48);
int a2=((int)(USART_RX_BUF[3] -48)*10 )+ (int)(USART_RX_BUF[4] -48);
int a3= a1+a2;
if(a3<10)
{
printf("= 0%d \r\n",a3);
}
else
{
printf("= %d \r\n",a3);
}
}
else if(USART_RX_BUF[2]==45)
{
int a1=((int)(USART_RX_BUF[0] -48)*10 )+ (int)(USART_RX_BUF[1] -48);
int a2=((int)(USART_RX_BUF[3] -48)*10 )+ (int)(USART_RX_BUF[4] -48);
int a3= a1-a2;
if(a3<10)
{
printf("= %d \r\n",a3);
}
else
{
printf("= %d \r\n",a3);
}
}
}
USART_RX_STA=0;
}
}
*/