day29:使用USART串口直接输出字符字模
在学习LCD液晶显示字符之前,先学习USART串口输出字符的原理。
工程结构:

bsp_usart.h
#ifndef __BSP_USART_H__ #define __BSP_USART_H__ #include "stm32f10x.h" #include "stdio.h" // ----------------------- 串口1-USART1 // 使用哪个串口(串口1..5) #define DEBUG_USARTx USART1 // APB2串口的同步时钟 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 // APB2系统时钟(因为串口USART1是挂载到APB2总线上的,所以要打开APB2总线的时钟) #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd // 串口通信的波特率 #define DEBUG_USART_BAUDRATE 19200 // ----------------------- USART GPIO 引脚宏定义 // GPIO引脚 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) // APB2系统时钟(因为串口USART1是挂载到APB2总线上的,所以要打开APB2总线的时钟) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd // GPIO引脚,发送接PA9,接收接PA10 #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_IRQ USART1_IRQn #define DEBUG_USART_IRQHandler USART1_IRQHandler /* 串口调试配置函数:配置串口的相关参数,使能串口 */ void DEBUG_USART_Config(void); /* 发送一个字节 */ void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch); /* 发送字符串 */ void Usart_SendString(USART_TypeDef* pUSARTx, char* str); #endif /* __BSP_USART_H__ */
bsp_usart.c
#include "./usart/bsp_usart.h"
/* 串口中断配置函数 */
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
/* 串口调试配置函数:配置串口的相关参数,使能串口 */
void DEBUG_USART_Config(void)
{
/* 结构体变量声明 */
GPIO_InitTypeDef GPIO_InitStructure; // GPIO
USART_InitTypeDef USART_InitStructure; // USART
/* ------------ 第一步:初始化GPIO */
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; // 引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速率
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 初始化结构体
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* ------------ 第二步:配置串口的初始化结构体 */
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
/* 配置串口的工作参数 */
// 波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 停止位
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(DEBUG_USARTx, &USART_InitStructure);
/* -------------------------------------------------------- */
// 串口中断优先级配置
//NVIC_Configuration();
// 使能串口接收中断
//USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
/* -------------------------------------------------------- */
/* ------------ 第三步:使能串口 */
USART_Cmd(DEBUG_USARTx, ENABLE);
}
/* 发送一个字节 */
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx, ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/* 发送字符串 */
void Usart_SendString(USART_TypeDef* pUSARTx, char* str)
{
unsigned int k=0;
do
{
Usart_SendByte(pUSARTx, *(str + k));
k++;
} while(*(str + k)!='\0');
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}
/* 重定向c库函数printf到串口,重定向后可使用printf函数 */
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
/* 重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 */
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
main.c
#include "stm32f10x.h" #include "./usart/bsp_usart.h" #include "./led/bsp_led.h" /* 邹 每个字符用2个字节来表示: 16行 16列(每一行有2个字节,每个字节8位,共16位,即16列),
使用字模软件自动生成的数组:PCtoLCD2002.exe */ uint8_t chacter_zou[] = { 0x20,0x00, 0x20,0x7C, 0x3E,0x44, 0x42,0x48, 0x84,0x48, 0x08,0x50, 0xFE,0x48, 0x02,0x48, 0x02,0x44, 0x7E,0x44, 0x02,0x44, 0x02,0x68, 0x02,0x50, 0xFE,0x40, 0x02,0x40, 0x00,0x40 }; // 通过串口直接输出字符 void print_chacter(uint8_t chacter[]); int main(void) { /* LED初始化 */ LED_GPIO_Config(); /* USART串口通信初始化 */ DEBUG_USART_Config(); // 使用printf函数将数据输出到上位机 printf("通过USART串口直接输入字模字符\r\n\r\n"); // 使用串口直接输入字符 print_chacter(chacter_zou); while(1); } void print_chacter(uint8_t chacter[]) { uint8_t i, j, ch; // 遍历16行 for(i=0; i<16; i++) { // 每一个字符用2个字节16位来表示 // 遍历第一个字节,8位 for(j=0; j<8; j++) { ch = (chacter[2*i]<<j) & 0x80; if(ch == 0) { printf(" "); } else { printf("*"); } } // 遍历第二个字节 for(j=0; j<8; j++) { ch = (chacter[2*i+1]<<j) & 0x80; if(ch == 0) { printf(" "); } else { printf("*"); } } // 遍历完一行要换行 printf("\r\n"); } }

实验结果:可以设置字体,字号大小等等


浙公网安备 33010602011771号