上一篇博文已经介绍了F0和F1系列的不同点,这里不再赘述,先上代码:
这里给出相关文档的下载路径:
链接: STM32F031G4中文编程手册.
/*GPIOA初始化配置 */
void GPIOA_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
/*初始化GPIOA时钟*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*复用 AF1,看手册*/
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
/* 配置PA9 ,PA10 串口*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //设置端口复用
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;/* 推挽输出或开漏输出 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 无、上拉或下拉 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;//50MHZ
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*485使能引脚*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_8);//初始化GPIOA8为低电平
}
这里在上一篇文章说过,GPIO要配置成复用功能映射表,此处补充一张复用图:
/*串口初始化配置 */
void USART_Config(void)
{
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*初始化USART1时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_InitStructure.USART_BaudRate = 2500000;//设置串口波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//设置工作模式
USART_InitStructure.USART_Parity = USART_Parity_No;//设置效验位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);//使能串口 1
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_Init(&NVIC_InitStructure); //初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
}
三、DMA配置
void MYDMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA1_MEM_LEN = 11;
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_BASE+0x28; //DMA外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_TX_BUF; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = DMA1_MEM_LEN; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel2, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
DMA_Cmd(DMA1_Channel2, ENABLE); //使能USART1 TX DMA1 所指示的通道
}
void MYDMA_Send(void)
{
DMA_Cmd(DMA1_Channel2, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel2, DMA1_MEM_LEN);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
四、串口485发送函数
串口中断函数
//串口1中断服务函数
void USART1_IRQHandler(void)
{
uint8_t Res;
//处理接收到的数据
if(USART_GetITStatus(USART1, USART_IT_RXNE))
{
Res =UART_Recive();//读取串口接收到的数据
if(Res == 0x1A)
{
RS_485_send();//485+DMA发送函数
}
}
/* 清除串口接收标志位 */
USART_ClearFlag(USART1,USART_FLAG_RXNE);
GPIO_ResetBits(GPIOA, GPIO_Pin_8); //接收模式
}
485发送函数
/*
RS485发送
*/
void RS_485_send(){
uint8_t i;
GPIO_SetBits(GPIOA, GPIO_Pin_8);//设置为发送模式
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
DMA_Send();
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
GPIO_ResetBits(GPIOA, GPIO_Pin_8); //接收模式
}
DMA发送函数
void DMA_Send(void)
{
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送
MYDMA_Send();
if(DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET)
{
DMA_ClearFlag(DMA1_FLAG_TC2);
}
//这里可以放其他东西,与发送数据同时进行
// GPIO_ResetBits(GPIOA, GPIO_Pin_8); //设置485为接收模式
}
代码运行时485接收到数据产生中断,并对数据进行判断,符合条件会使用DMA+485讲数据发送出去。因为工作时间紧张,所有没有对代码做详细讲解,若有疑问自行留言,我看到会回复。此篇为STM32F0系列开篇,后面会继续更新内外部时钟切换,SPI连续发送24位甚至更多位数据,发送时钟连续,我在做这个的时候全网没找到相应介绍,真心难死我了,就到这里,下篇见,如若在我未更新便有人遇到SPI的问题,可在此留言催跟。