STM32F103RB 实作笔记(九)- PWM + SPI +MAX6675 整合试验

发布者:sokaku最新更新时间:2022-07-20 来源: csdn关键字:STM32F103RB  PWM  SPI  MAX6675 手机看文章 扫描二维码
随时随地手机看文章

个人工作上的关系,需要做一款温度控制风扇速度的控制器,还需要能够看到温度和PWM的值。于是我用这个不熟悉的 STM32F103 试试,顺便把 PWM 和 SPI 也了解一番。

一开始当然也是跌跌撞撞,搞了很久才弄清楚。这篇笔记记录怎么做好的过程。

实验的过程是以正点原子 STM32F103 nano开发板和他附上的练习程式开始。


参考 NANO 的程式

依照正点原子的教材,跑了一下 nano 程式,执行了 OK!原来的程式里面 PWM 用 TIM3 的 channel_1 控制 PC6 的 LED 闪烁。SPI 是用 SPI2 控制 W25Q16 进行读写。


由于 PWM 和 SPI2 都被开发板占有,我选了另外一组 TIM2_CH2 和 SPI1 做我的控制件。作业如下:


PWM

从原来的程式,可以知道要调整那么多开关,以下是 nano 的 测试程式内容:


void TIM3_PWM_Init(u16 arr,u16 psc) 

{                   

  RCC->APB1ENR|=1<<1;      //TIM3 时钟使能   

  RCC->APB2ENR|=1<<4;          //使能 PORTC 时钟   

  GPIOC->CRL&=0XF0FFFFFF;//PC6 输出 

  GPIOC->CRL|=0X0B000000;    //复用功能输出         

  RCC->APB2ENR|=1<<0;          //使能 AFIO 时钟   

  AFIO->MAPR&=0XFFFFF3FF; //清除 MAPR 的[11:10] 

  AFIO->MAPR|=3<<10;              //部分重映像,TIM3_CH1->PC6 

  TIM3->ARR=arr;          //设定计数器自动重装值   

  TIM3->PSC=psc;          //预分频器不分频 

  TIM3->CCMR1|=7<<4;          //CH1 PWM2 模式       

  TIM3->CCMR1|=1<<3;        //CH1 预装载使能         

  TIM3->CCER|=1<<0;            //OC1  输出使能        

  TIM3->CR1=0x0080;            //ARPE 使能   

  TIM3->CR1|=0x01;              //使能定时器 3      

}           


这里直接写正确的进行方式,不讲其他的故事了


设定 TIMx_CHx 有下面几个部分:

1. 查看 APIO 的資料,把 TIM2 的 “REMAP” 里面对应的 GPIO pin 脚选定。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

参考 nano 的预留 IO 脚,我们选择 TIM2_CH2, 脚位是 PA1. 这个时候 要记得 APIO_MAPR 的 TIM2_REMAP 要选择 “00" 或 ”10“.


2. 进RCC,要把 TIM2 的开关打开

在这里插入图片描述

这个是 RCC->APB1ENR 的内容,可以看到 TIM3 bit_1, TIM2 是在 bit_0. 所以,还要把 AFIO 输出的开关 打开,改成


RCC->APB1ENR|=1<<0;      //TIM2 时钟使能

RCC->APB2ENR|=1<<0;     //select AFIO output


4. 把 GPIO 的相关开关打开

这个部分要很熟悉才是, 但是记得 用 0xB 设定 pin 脚输出模式:


RCC->APB2ENR|=1<<2; //PORTA 

GPIOA->CRL&=0XFFFFFF0F; //PA1

GPIOA->CRL|=0X000000B0; //'1011 to PA1


5. 把 APIO 的开关打开

主要就是 复用重映射和调试I/O配置寄存器(AFIO_MAPR) 的设定

在这里插入图片描述

   AFIO->MAPR&=0XFFFFFCFF; // '1100' to clear REMAPR[9:8] TIM2


6. 把 TIM2 的相关开关设定好

这个部分就是抄袭原来的范例,没有变更:


TIM2->ARR=arr; //set frequency to TIM2  

TIM2->PSC=psc; //psc

TIM2->CR1=0x0080;    //ARPE 

TIM2->CR1|=0x01;    //3 


7. 把 CH2 的相关开关设定好

这里要特变注意到的是 CH1,CH2 在 TIMx_CCMR1 ;CH3,CH4 在 TIMx_CCMR2. 两个不同寄存器里面。检查寄存器的结构,可以看出 bit 0-7 一组(CH1, CH3)和 bit 8~15(CH2, CH4);

在这里插入图片描述
在这里插入图片描述

因为我们选的是 CH2, 所以设定在 CCMR1.

CCER 没有变化,直接拿过来。


//----TIM2_CH2 setting--

TIM2->CCMR1|=7<<12;  //CH2 PWM2CH2->  

TIM2->CCMR1|=1<<11; //CH2 PWM2CH2->   

TIM2->CCER|=1<<4;    //CC2E_OC2


8. 最后一个很重要 CCRx

这一段資料在 pwm.h 的 Define 里面。就是 每一个CH 都有自己的 CCR

CH1 对 CCR1,CH2 对 CCR2,CH3 对 CCR3,CH4 对 CCR4.下面示范了几个不同写法;


//TIM3->CCR1 LED6 

#define LED6_PWM_VAL TIM3->CCR1 

//TIM3->CCR2 LED7 

#define PC7_PWM_VAL TIM3->CCR2 

//TIM2->CCR3 PB10

#define PB10_PWM_VAL TIM2->CCR3 

//TIM2->CCR2 PA1

#define PA1_PWM_VAL TIM2->CCR2 


如果对直接修改的过程没有信心, 可以先改一个 TIM3_CH2 的过程测试(PC7 LED 明暗)。多验证几种,多改几次会有信心些。

以下是修改完成的 PWM 程式

pwm.c


//

//change it to TIM2 CH2-PA1

//arr the valeu to auto-reload

//pscPrescaler value--f CK_PSC /(PSC[15:0]+1)


void TIM2_PWM_Init(u16 arr,u16 psc)

//--------GPIOB-- setting ------------------------


RCC->APB2ENR|=1<<2; //PORTA 

GPIOA->CRL&=0XFFFFFF0F; //PA1

GPIOA->CRL|=0X000000B0; //'1011 to PA1

//---TIM2 setting   

RCC->APB1ENR|=1<<0;     //TIM2 

RCC->APB2ENR|=1<<0;     //select AFIO output

    AFIO->MAPR&=0XFFFFFCFF; //清'1100' to clear REMAPR[9:8] TIM2

//---TIM2-CH2 setting    

// AFIO->MAPR|=0xE<<8;      //TIM2_REMAP10=10,->'1110'

TIM2->ARR=arr; //set frequency to TIM2  

TIM2->PSC=psc; //psc

TIM2->CR1=0x0080;    //ARPE 

TIM2->CR1|=0x01;    //3

//----TIM2_CH2 setting--

TIM2->CCMR1|=7<<12;  //CH2 PWM2CH2->  

TIM2->CCMR1|=1<<11; //CH2 PWM2CH2->   

TIM2->CCER|=1<<4;    //CC2E_OC2    

}


pwm.h


#ifndef __PWM_H

#define __PWM_H

#include "sys.h"


//  

//try a new PWM by TIM2   

//


//TIM3->CCR1 LED6 

#define LED6_PWM_VAL TIM3->CCR1 

//TIM3->CCR1 LED6 

#define PA7_PWM_VAL TIM3->CCR2 

//TIM2->CCR3 PB10

#define PB10_PWM_VAL TIM2->CCR3 

//TIM2->CCR2 PA1

#define PA1_PWM_VAL TIM2->CCR2 


void TIM3_PWM_Init(u16 arr,u16 psc);

void TIM2_PWM_Init(u16 arr,u16 psc);

#endif


pwm.h 里面保留了 nano 开发板原来的 PC6 亮度调变程式;目的在视觉观察程式是否正常用的。


SPI

SPI 的原件很多,应用也很广,在网上也能够取得许多不同的程式。这次试验的目的在用 SPI1 接收 MAX6675 的讯号。这里先调整 SPI。

下面是 nano 板的程式,选的是 SPI2.

spi2.c


//-------------------------------------------------

void SPI2_Init(void) 

{     

  RCC->APB2ENR|=1<<3;        //PORTB 时钟使能       

  RCC->APB1ENR|=1<<14;          //SPI2 时钟使能   

  //这里只针对 SPI 口初始化 

  GPIOB->CRH&=0X000FFFFF;   

  GPIOB->CRH|=0XBBB00000;  //PB13/14/15 复用             

  GPIOB->ODR|=0X7<<13;        //PB13/14/15 上拉 

  SPI2->CR1|=0<<10;      //全双工模式   

  SPI2->CR1|=1<<9;        //软件 nss 管理 

  SPI2->CR1|=1<<8;       

  SPI2->CR1|=1<<2;        //SPI 主机 

  SPI2->CR1|=0<<11;      //8bit 数据格式   

  SPI2->CR1|=1<<1;        //空闲模式下 SCK 为 1 CPOL=1 

  SPI2->CR1|=1<<0;        //数据采样从第二个时间边沿开始,CPHA=1     

  //对 SPI2 属于 APB1 的外设.时钟频率最大为 36M. 

  SPI2->CR1|=3<<3;        //Fsck=Fpclk1/256 

    SPI2->CR1|=0<<7;        //MSBfirst       

  SPI2->CR1|=1<<6;        //SPI 设备使能 

  SPI2_ReadWriteByte(0xff);    //启动传输       

}     


//---------------------------------------------------

u8 SPI2_ReadWriteByte(u8 TxData) 

{     

  u16 retry=0;           

  while((SPI2->SR&1<<1)==0)  //等待发送区空   

  { 

    retry++; 

    if(retry>=0XFFFE)return 0;   //超时退出 

  }           

  SPI2->DR=TxData;            //发送一个 byte   

  retry=0; 

  while((SPI2->SR&1<<0)==0)    //等待接收完一个 byte     

  { 

    retry++; 

    if(retry>=0XFFFE)return 0;  //超时退出 

  }                           

  return SPI2->DR;                      //返回收到的数据                 

}         


spi2.h


#ifndef __SPI_H 

#define __SPI_H 

#include "sys.h" 

// SPI 总线速度设置   

#define SPI_SPEED_2        0 

#define SPI_SPEED_4        1 

#define SPI_SPEED_8        2 

#define SPI_SPEED_16       3 

#define SPI_SPEED_32       4 

#define SPI_SPEED_64       5 

#define SPI_SPEED_128      6 

#define SPI_SPEED_256      7   

void SPI2_Init(void);          //初始化 SPI2 口 

void SPI2_SetSpeed(u8 SpeedSet);    //设置 SPI2 速度       

u8 SPI2_ReadWriteByte(u8 TxData);  //SPI2 总线读写一个字节 

#endif 


1. 查看 APIO 的資料,把 SPI1 的 "REMAP” 里面对应的 GPIO pin 脚选定。

选 pin 脚的事情要好好看看!


A。 没有 SPI2 的复用資料?

因为没有 SPI2 資料表比较,很容易就忽略了 **“NSS”**的使用技巧。从复用表上了解到需要用到的 pin 脚有 4 个,NSSSCKMISOMOSI. 再看看 nano 的程式


  GPIOB->CRH|=0XBBB00000;  //PB13/14/15 复用             

  GPIOB->ODR|=0X7<<13;        //PB13/14/15 上拉 


只定义了 3 个 脚位,就是 SCKMISOMOSI。nano 資料说明是 “使用的是 PB13、14、15 这 3 个(SCK.、MISO、MOSI,CS 使用软件管理方式),所以设置这三个为复用功能 IO”。

再查了下网络其他讨论 STM32F103 的文章,有许多负面的声音。不过,没关系,我们只要知道怎么用就好。


B。选用 nano 预留,没其他使用的脚位

SPI1 的 PA4567 这一组可以使用。

在这里插入图片描述

为了日后使用方便,我们把复用 GPIO 另外定义如下:

复用的 IO 要用 0xB. 没有定义 PA4.


void SPI1_GPIO_Init(void)

{

    RCC->APB2ENR|=1<<3;       //PORTA selected  

AFIO->MAPR&=!(1)<<0; //SPI1_REMAP=0, pin out PA4,5,6,7

//SPI set GPIO output

GPIOA->CRL&=0X000FFFFF; //clear PA5,6,7

GPIOA->CRL|=0XBBB00000;//PA5,6,7 '1011' 

GPIOA->ODR|=0X7<<5;    //PA5,6,7 high

}


2. 进RCC,要把 SPI1 的开关打开

从資料上看到 SPI1 是在 RCC->APB2ENR 的 pin 12.

在这里插入图片描述

所以:


RCC->APB2ENR|=1<<12;      //SPI1 enable, APB2ENR bit12 


3.设定 SPI1 的相关参数。

参考STM32F103 的 資料,SPI 的主要设定都在 CR1,如下:

在这里插入图片描述

再参考其他程式 和 nano 板的程式,改写成下面这样:


// ====setting SPI    

    SPI1->CR1|=0<<10;// dual-channel

SPI1->CR1|=1<<8;  //if SSM=1,internal slave


SPI1->CR1|=1<<2; //set as a SPI master

[1] [2]
关键字:STM32F103RB  PWM  SPI  MAX6675 引用地址:STM32F103RB 实作笔记(九)- PWM + SPI +MAX6675 整合试验

上一篇:STM32使用UCOSII支持低功耗模式
下一篇:STM32F103RB 实作笔记(八)- IWDG 内部看门狗试验

推荐阅读最新更新时间:2024-11-13 21:06

关于STM32的 一个TIM1 的PWM程序和PWM简单使用
高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。共有4个通道有 死区有互补。 先是配置IO脚: GPIO_InitTypeDef GPIO_InitStructure; /* PA8设置为功能脚(PWM) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*P
[单片机]
关于STM32的 一个TIM1 的<font color='red'>PWM</font>程序和<font color='red'>PWM</font>简单使用
微芯有刷直流电机控制方案
 有刷直流电机通过电刷进行换向。以下是关于有刷直流电机的一些关键点: 典型的转子(也就是电枢)上有绕组,并且在其末端连有换向器 电刷与换向部分连接和断开,从而将能量传递到电枢 永磁直流电机的定子(或外部机筒)将有两个或更多个永磁磁极 通电绕组和定子磁体的相反极性互相作用,从而导致转子旋转直到与定子同相位 一旦转子与定子对齐,电刷与换向器接触并导通下一个绕组 由于速度和转矩与所应用的电压/电流成正比,因而有刷直流电机控制起来相对容易。由于电枢上有绕组,因而转子很重,较大的惯性使其较难启动和停止。转子上的绕组会产生热量,并且较难散热。 有刷直流电机的主要特性 良好的可控性:开/关,成正比 线性转
[嵌入式]
STM32—cubeMX+HAL库的SPI接口使用
摘要: 本文主要介绍STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码。 STM32之SPI简介: (1)SPI协议【Serial Peripheral Interface】 串行外围设备接口,是一种高速全双工的通信总线。主要用在MCU与FLASH\ADC\LCD等模块之间的通信。 (2)SPI信号线 SPI 共包含 4 条总线。 SS(Slave Select):片选信号线,当有多个SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。 SCK (S
[单片机]
STM32—cubeMX+HAL库的<font color='red'>SPI</font>接口使用
STM32学习笔记(5):通用定时器PWM输出
1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。 STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。 1.1PWM输出模式 STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和
[单片机]
【STM32学习笔记】USART波特率 vs SPI速率
上一篇学习笔记介绍了USART硬件流控,相信大家理解了为什么要做流控,硬件流控与软件流控的区别,以及硬件流控如何处理。 本篇文章将与大家探讨USART波特率 vs SPI速率。这里提出一个问题,为什么USART的波特率是内核时钟的1/8或者1/16,而SPI最快的频率可以是内核时钟的1/2。 请大家带着这个问题来阅读本文。 串口和SPI内部时钟 在回答上面问题之前,需要先了解STM32内部时钟的概念,尤其是串口和SPI的内部时钟。 STM32里包含有系统时钟、AHB时钟和APB时钟。APB时钟来源于AHB,AHB时钟来源于系统时钟。 从上图中可以看出,时钟就像流水一样,从时钟源汇聚到系统时钟上,再从系统时
[单片机]
基于24V电源的双环电流型PWM控制器的设计
0 引言 电压型PWM是指控制器按反馈电压来调节输出脉宽,而电流型PWM是指控制器按反馈电流来调节输出脉宽。电流型PWM是在脉宽比较器的输入端,直接用流过输出电感线圈电流的信号与误差放大器输出信号进行比较,从而调节占空比,使输出的电感峰值电流跟随误差电压变化而变化。由于结构上有电压环、电流环双环系统,因此,无论开关电源的电压调整率、负载调整率和瞬态响应特性都有提高,是目前比较理想的新型PWM控制器。 1 双环电流型PWM控制器工作原理 双环24V电源电流型脉宽调制(PWM)控制器是在普通电压反馈PWM控制环内部增加了电流反馈的控制环节,因而除了包含电压型PWM控制器的功能外,还能检测开关电流或电感电流,实现电压电流的双环控制。双环电
[嵌入式]
SPI驱动的移植
为了使用SPI 驱动,必须在配置Linux 编译选项时,开启相应的SPI 选项,如下所示 - Device Drivers - SPI support SPI support *** SPI Master Controller Drivers *** -*- Bitbanging SPI master * Samsung S3C24XX series SPI Samsung S3C24XX series SPI by GPIO *** SPI Protocol Masters *** SPI EEPROMs from most vendors
[单片机]
具内部 PWM 发生器的 40VIN / 60VOUT 5A 恒流恒压转换器
加利福尼亚州米尔皮塔斯 (MILPITAS, CA) – 2013 年 4 月 18 日 – 凌力尔特公司 (Linear Technology Corporation) 推出 DC/DC 转换器 LT3954,该器件具有内部 5A 开关,可用作恒定电流源和恒定电压稳压器。器件的内部 PWM 调光发生器使其非常适合驱动大电流 LED,它也有适合于充电电池和超级电容的功能。LT3954 的 4.5V 至 40V 输入电压范围适合包括汽车、工业和建筑照明等多种应用。 LT3954 使用一个内部 5A, 40V N 沟道 MOSFET,能够采用额定 12V 输入驱动高达 8 个 650mA 白光 LED,从而输送超过 20W 的功率
[电源管理]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved