STM32的串⼝通信UARTTTL
常⽤的串⼝pin
STM32的串⼝是基础通信⽅式, 每个型号都带多组串⼝, ⼀般都使⽤默认的组, 可以参考芯⽚的datasheet, 去看pinout and pin definitions, 对于stm32f103c8t6, 这是48pin的芯⽚, 提供3组串⼝, 如果使⽤3组, 各组串⼝的pin脚为
USART2 - A2, A3
第一次见面PA0: USART2_CTS
PA1: USART2_RTS
PA2: USART2_TX
PA3: USART2_RX
led灯珠怎么测试好坏
PA4: USART2_CK
USART1 - A9, A10
PA8: USART1_CK
PA9: USART1_TX
PA10: USART1_RX
PA11: USART1_CTS
PA12: USART1_RTS
USART3 - B10, B11
PB10: USART3_TX
PB11: USART3_RX
PB12: USART3_CK
PB13: USART1_CTS
PB14: USART1_RTS
串⼝通信编程
⼀般通过以下的步骤实现串⼝通信
1. 申请内存作为buffer, 声明标记位和buffer指针
简单的例⼦
u8 usart_buf[100] = {0};
u16 index1 = 0, flag1 = 0;
复杂的例⼦
#define TTL_BufferLength ((uint16_t)0x0040)
#define TTL_WriteOk ((uint16_t)0x0000)
#define TTL_BufferOverrun ((uint16_t)0x0001) // full flag
#define TTL_BufferUnderrun ((uint16_t)0x0002) // empty flag
/
* Private types -------------------------------------------------------------*/
typedef struct
党务公开总结{
uint16_t size; /* The size of the buffer */
uint16_t start; /* The index of the next character to nd */
uint16_t end; /* The index at which to write the next character */
char* elems; /* The location in memory of the buffer */
} TTL_BufferTypeDef;
/* Private variables ----------------------------------------------------------*/
TTL_BufferTypeDef cb;
/* Private Methods -----------------------------------------------------------*/
void TTL_Buffer_Init()
{
cb.size = TTL_BufferLength;
cb.start = 0;
cb.elems = calloc(cb.size, sizeof(char));
}
void TTL_Buffer_Free()
{
free(cb.elems);
}皇太极为什么恨大玉儿
uint16_t TTL_Buffer_IsFull()
{
return (cb.end + 1) % cb.size == cb.start;
}
uint16_t TTL_Buffer_IsEmpty()
{
d == cb.start;
}
uint16_t TTL_Buffer_Write(char c)
{
// check for a buffer overrun
if (TTL_Buffer_IsFull()) {
return TTL_BufferOverrun;
} el {
cb.d] = c;
}
return TTL_WriteOk;
}
uint16_t TTL_Buffer_Read(char* c)
{
// check for a buffer underrun
if (TTL_Buffer_IsEmpty()) {
return TTL_BufferUnderrun;
} el {
*c = cb.elems[cb.start];
cb.start = (cb.start + 1) % cb.size;
}
}
2. 初始化UART端⼝: 使能GPIO, UART, NVIC /* Public Methods -----------------------------------------------------------*/
void TTL_Init()
{
// Structures to hold the initialisation data
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// enable the peripherals we're going to u
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// Usart1 Tx is on GPIOB pin 6 as an alternative function
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// Connect pin 6 to the USART
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
// fill in the interrupt configuration
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// init the USART to 8:N:1 at 9600 baud as specified in the
/
/ TTL data sheet
USART_InitStruct.USART_BaudRate = 9600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
// Enable USART1 peripheral
USART_Cmd(USART1, ENABLE);
// ensure USART1 interrupts are off until we have data
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
// prepare the buffer
TTL_Buffer_Init();
}
3. 实现中断处理⽅法读消息
/* Public Methods -----------------------------------------------------------*/
/*
* Handles all interrupts for USART1.
*/
void USART1_IRQHandler(void)
{
// is this interrupt telling us that we can nd a new character?
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
// is there something for us to read?
if (TTL_Buffer_IsEmpty()) {
// no, disable the interrupt
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
} el {
// yes, get the next character from the buffer
char c = 0x00;
TTL_Buffer_Read(&c);
// nd it to the device
USART_SendData(USART1, c);
}
}
}
4. ⼯具⽅法: 写消息, 反初始化(⾮必须)
注意在每次调⽤USART_SendData这个⽅法之后, 都需要阻塞判断 USART_FLAG_TC 是否为SET才能继续往下执⾏. ...
USART_SendData(USART1, *str++);
while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
...
例如
/* Public Methods -----------------------------------------------------------*/
void TTL_DeInit()
绿豆汤{
// disable the interrupts
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
// free the buffer
TTL_Buffer_Free();
}
uint16_t TTL_IsBufferFull()
{
return TTL_Buffer_IsFull();
}
uint16_t TTL_WriteMessage(char* text, uint16_t length)
{
葛福鸿// index into the character array
uint16_t i = 0;
// return value
uint16_t rv = TTL_WriteOk;
while(length--) {
脚大穿什么鞋好看USART_SendData(USART1, *text++);
// USART_SendData(USART1,(uint16_t) *text++);
// Loop until the end of transmission
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
}
/
/ enable the interrupt to nd the message
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
return rv;
}
代码例⼦
这是⼀个完整的代码例⼦, 适⽤于STM32F103
#include "sys.h"
#include "usart.h"
#include "delay.h"
u8 usart1_buf[100] = {0}, usart2_buf[100] = {0}, usart3_buf[100] = {0};
u16 index1 = 0, index2 = 0, index3 = 0, flag1 = 0, flag2 = 0, flag3 = 0;
void uart_init(u32 bound){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(
RCC_APB1Periph_USART2 | RCC_APB1Periph_USART3, ENABLE);
//使能USART1,GPIOA时钟
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
/*************UART1********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复⽤推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输⼊
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //⼦优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_InitStructure.USART_BaudRate = bound;//串⼝波特率
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); //初始化串⼝1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串⼝接受中断
USART_Cmd(USART1, ENABLE); //使能串⼝1
/***************UART2******************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复⽤推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输⼊
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.3
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //⼦优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_InitStructure.USART_BaudRate = bound;//串⼝波特率
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(USART2, &USART_InitStructure); //初始化串⼝2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串⼝接受中断
USART_Cmd(USART2, ENABLE); //使能串⼝2
/****************UART3***********************/
//USART3_TX GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复⽤推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.10
//USART3_RX GPIOB.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PB11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输⼊
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.11
//Usart3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级4
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //⼦优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_InitStructure.USART_BaudRate = 115200; //串⼝波特率
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(USART3, &USART_InitStructure); //初始化串⼝3
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启串⼝接受中断
USART_Cmd(USART3, ENABLE);
}
/**
每个字节⼀个中断, 这⾥⽤0x0a作为⼀条消息读取结束
*/
void USART1_IRQHandler(void)
二十元钱{
u16 code;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART1, USART_IT_RXNE);//Removal of receiving interrupt flag
code = USART_ReceiveData(USART1);
usart1_buf[index1] = code;
index1++;
if(code == 0x0a) {
index1 = 0;
flag1 = 1;
}
}
}
void USART2_IRQHandler(void)
{
u16 code;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
code=USART_ReceiveData(USART2);
usart2_buf[index2] = code;
index2++;
if(code == 0x0a) {
index2 = 0;
flag2 = 1;
}
}
}
void USART3_IRQHandler(void)
{
u16 code;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
code = USART_ReceiveData(USART3);
usart3_buf[index3] = code;
index3++;
if(code == 0x0a) {
index3 = 0;
flag3 = 1;
}
}
}
void USART1_Send(u8 *str)
{
while(*str != 0x0a) {
USART_GetFlagStatus(USART1, USART_FLAG_TC);
USART_SendData(USART1, *str++);
while( USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
}
USART_SendData(USART1, 0x0a);
}
void USART2_Send(u8 *str)
{
while(*str != 0x0a) {
USART_GetFlagStatus(USART2, USART_FLAG_TC);
USART_SendData(USART2, *str++);
while( USART_GetFlagStatus(USART2,USART_FLAG_TC) != SET);
}
USART_SendData(USART2, 0x0a);
}