本代码会使用寄存器和库函数相结合
要求:一.初始串口,从串口用printf函数输出内
二.串口输入可控制B0闪灯快慢"SPEED1",快闪1秒闪5次,"SPEED2",1秒闪1次
三.输入"GOOD" 串口返回“China”,输入“Other”返回“Nippon”
首先建立allfun.c和allfun.h输入存放我们需要用到函数
需要了解stm32硬件的IO规划
目录
一 (1) 首先根据题目要求在allfun.c中初始化串口,用到串口1,TIM2小灯闪烁,中断优先级
二 (1) 我们为了减轻CPU的工作负担,直接用CPU的“小秘书”--DMA来完成串口一系列的计算
一 (1) 首先根据题目要求在allfun.c中初始化串口,用到串口1,TIM2小灯闪烁,中断优先级
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//设置优先级分组:先占优先级0位,从优先级4位
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
一 (2) 设置函数 ch通道 PCLK2主频 BOUND波特率 parity奇偶
void uart_init(char ch,unsigned long int pclk2,unsigned long int bound,char parity)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);
mantissa=temp;
fraction=(temp-mantissa)*16;
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; // 端口B开时钟
RCC->APB2ENR|=1<<14; // USART1使能
if (ch==1) {
GPIOA->CRH&=0xfffff00f;GPIOA->CRH|=0x000004B0; //引脚输入输出设置
RCC->APB2RSTR|=1<<14; //复位USART1
RCC->APB2RSTR&=~(1<<14); //恢复正常状态
USART1->BRR=mantissa; // 10,0001,0001,1100
if (parity==0) USART1->CR1|=0X211C; // 使能 中断开 空闲中断 TE RE 位10开位9,位9 0偶1奇 位8中断开
if (parity==1) USART1->CR1|=0X371C; //有校验位12为1即9位 故为3,11
if (parity==2) USART1->CR1|=0X351C; // 使能 中断开 空闲中断 TE RE 位10开位9,位9 0偶1奇 位8中断开
USART1->CR3|=1<<6; // DMAR接收使能
}
一 (3) 设置函数 重定向输出到串口,接着根据题目要求在我们输入字符时,也会有相应的字符输出,所以需要在allfun.c中加一个printf函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
assert_param(IS_USART_ALL_PERIPH(USARTx)); // Check the parameters
assert_param(IS_USART_DATA(Data));
USARTx->DR = (Data & (uint16_t)0x01FF); //Transmit Data
}
int fputc(int ch, FILE *f)
{
USART_SendData(USART1,(uint8_t)ch);
while((USART1->SR&0x80) == 0) ;
return ch;
}}
ps:记得在魔术棒里打钩哦
一 (4) 在stm32f10x_it.c写入中断函数USART1和TIM2中断函数
#include "stm32f10x_it.h"
#include <allfun.h>u16 tim;
void TIM2_IRQHandler(void)
{
if(TIM2->SR&0X0001)
{
if (tim<5000) tim++;
}
TIM2->SR&=~1;
}void USART1_IRQHandler(void)
{
char kkl=0;
if (USART1->SR&(1<<4))
{
DMA1_Channel5->CCR&=~(1<<0); //关闭DMA通道
USART1->CR3&=~(1<<6); //关闭USART1串口的DMA接收
rf=300-DMA1_Channel5->CNDTR;
kkl=USART1->SR;kkl=0;kkl+=USART1->DR; //读取一下即可清除标志
}
}
这样,串口的初始化及定义就完成啦 。
二 (1) 我们为了减轻CPU的工作负担,直接用CPU的“小秘书”--DMA来完成串口一系列的计算
void MYDMA_Config(DMA_Channel_TypeDef *DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
u32 DR_Base; //做缓冲用,不知道为什么.非要不可
RCC->AHBENR|=1<<0; //开启DMA1时钟
DR_Base=cpar; //外设地址
DMA_CHx->CPAR=DR_Base; //DMA1 外设地址cpar
DMA_CHx->CMAR=(u32)cmar; //DMA1,存储器地址
DMA1_MEM_LEN=cndtr; //保存DMA传输数据量
DMA_CHx->CNDTR=cndtr; //DMA1,传输数据量
DMA_CHx->CCR=0; //复位
DMA_CHx->CCR|=0<<4; //0读外设 1从存储器读
DMA_CHx->CCR|=1<<5; //0普通模式 1循环模式
DMA_CHx->CCR|=0<<6; //外设地址非增量模式
DMA_CHx->CCR|=1<<7; //存储器增量模式
DMA_CHx->CCR|=0<<8; //外设数据宽度为8位 9,8位 00 8 01 16 10 32
DMA_CHx->CCR|=0<<10; //存储器数据宽度8位 11,10位 同上
DMA_CHx->CCR|=1<<12; //中等优先级
DMA_CHx->CCR|=0<<14; //0非存储器到存储器模式,1存储器到非存储器模式,
}void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
MYDMA_Config(DMA1_Channel5,(u32)&USART1->DR,(u32)buf,300);//DMA1通道5,外设为串口1,存储器为SendBuff,长度100.
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
USART1->CR3|=1<<6;
}
三 (1) 最后定义一下初始化函数
void init(void)
{
SystemInit();
RCC->APB2ENR|=1<<3;
RCC->APB2ENR|=1<<2;
GPIOB->CRL&=0X00FFFF00;
GPIOB->CRL|=0X330000B3;
NVIC_Configuration();RCC->APB1ENR|=1<<0; //tim2 enable
TIM2->ARR=9;
TIM2->PSC=7199;
TIM2->DIER|=1<<0;
TIM2->DIER|=1<<6;
TIM2->CR1|=0x01;
tim=0;
MYDMA_Enable(DMA1_Channel5);
uart_init(1,72,115200,0);
MYDMA_Enable(DMA1_Channel5);
ps:记得要在allfun.h中申明,B0进行宏定义
#ifndef __ALLFUN_H
#define __ALLFUN_H#include <stm32f10x.h>
#include <misc.h>
#include <stdio.h>void init(void);
void NVIC_Configuration(void);
void MYDMA_Config(DMA_Channel_TypeDef *DMA_CHx,u32 cpar,u32 cmar,u16 cndtr);
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
void uart_init(char ch,unsigned long int pclk2,unsigned long int bound,char parity);
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
int fputc(int ch, FILE *f);extern u16 tim;
extern char buf[300],rf;
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //
#define led PBout(0)
#endif
四 (1) 主函数里利用数组实现功能
#include <allfun.h>
#include <string.h>int main(void)
{
u16 i,k2;
init();
while(1)
{
if (rf)
{
if (buf[0]=='G'&&buf[1]=='O'&&buf[2]=='O'&&buf[3]=='D') {led=0;printf("China\r\n");}
if (buf[0]=='O'&&buf[1]=='T'&&buf[2]=='H'&&buf[3]=='E'&&buf[4]=='R') {led=1;printf("Nippon\r\n");}
if (buf[0]=='S'&&buf[1]=='P'&&buf[2]=='E'&&buf[3]=='E'&&buf[4]=='D'&&buf[5]=='1') {k2=100;printf("SPEED1\r\n");}
if (buf[0]=='S'&&buf[1]=='P'&&buf[2]=='E'&&buf[3]=='E'&&buf[4]=='D'&&buf[5]=='2') {k2=500;printf("SPEED2\r\n");}
for(i=0;i<300;i++) buf[i]=0;
MYDMA_Enable(DMA1_Channel5);
}
if(tim>=k2)
{
tim=0;
led=!led;
}
}}
五.最后打开串口进行调试
这样我们就完成啦
六.总结
1.DMA设置,接收USART信息
2.USART1串口设置,波特率设置等
3.TIM中断,B0灯闪烁
4.printf串口输入打印
5.初始化函数
6.主函数里写入算法实现其功能
7.打开串口进行调试