1. Trang chủ
  2. » Công Nghệ Thông Tin

Thực hành lập trình vi điều khiển STM32L152 GPIO, SYSTICK TIMER, PWM, ADC

51 925 16

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 51
Dung lượng 1,16 MB
File đính kèm TH LẬP TRÌNH VI ĐIỀU KHIỂN CHIP STM32L152.rar (860 KB)

Nội dung

Lý thuyết và code kèm theo tương đối đầy đủ các bài thực hành GPIO, SYSTICK, PWM và ADC sách lập trình vi điều khiển STM32L152 Embedded Systems with ARM CortexM Microcontrollers in Assembly Language and C (Third Edition – Dr Yifeng Zhu) nội dung bao gồm: bật tắt led bằng nút nhấn, bật tắt led bằng delay SysTick Timer, tăng giảm độ sáng đèn bằng xung PWM, thay đổi điện áp đầu ra bằng cách sử dụng triết áp và hiển thị kết qua lên màn hình LCD ADC

Trang 1

LẬP TRÌNH VI ĐIỀU KHIỂN STM32L152

(Sách Embedded Systems with ARM Cortex-M Microcontrollers

in Assembly Language and C (Third Edition) – Dr Yifeng Zhu )

Nội dung: Lý thuyết và mã nguồn các bài thực hành trên chip STM32L152RC các bài GPIO, SysTick Timer, PWM và ADC

I BÀI THỰC HÀNH CHƯƠNG 12 –GPIO (GENERAL PURPOSE INPUT OUTPUT) - BẬT TẮT ĐÈN BẰNG NÚT NHẤN

Lab 1: Interfacing Push-button and LED Instructor: Prof Yifeng Zhu Spring

2015

SƠ ĐỒ KHỐI:

Trang 2

MÃ NGUỒN BẬT TẮT LED BẲNG BUTTON

Yêu cầu : Thiết lập các chân PB.6, PB.7 là ngõ ra nối với các led xanh dương và xanh lá, chân PA.0 là đầu vào kết nối với nút nhấn của vi điều khiển, khi nhấn nút các đèn xanh dương và xanh lá thay đổi trạng thái

Trang 3

}

void LED_BLUE(){ // set pin x I/O mode as GP Output

GPIOB->MODER &=~(0x03<<(2*6)); // reset state

GPIOB->MODER |=(0x01<<(2*6)); // set pin x as a digital output 01

GPIOB->OTYPER &=~(1<<6); // output type push-pull 0

GPIOB->OSPEEDR &=~(0x03<<(2*6)); // set I/O speed // set mark

GPIOA->MODER &=~(0x03); // set pin 0 I/O mode as GP input 00

GPIOA->OTYPER &=~(0x1); //output type pushpull 0

GPIOA->OSPEEDR &=~(0x03); //mark

Trang 4

GPIO_Clock_Enable(); //enable port A and B

BUTTON_A(); //config PA0

GPIOB->ODR |=1<<7; //turn off a yellow led

GPIOB->ODR &=~(1<<6); //turn on a blue led

while (1){

if ((GPIOA->IDR &1) ==1) { // button is pressed

GPIOB->ODR ^=1<<6;

//change status of led 6

GPIOB->ODR ^=1<<7;

//change status of led 7

for (delay = 0; delay < 100000; delay++){} //delay for a range time

Trang 5

ECE 271 Microcomputer Architecture and Applications - Lab 5: System Timer

(SysTick) Instructor: Prof Yifeng Zhu Spring 2015

A : LÝ THUYẾT

- SysTick là một chức năng định thời được tích hợp vào phần cứng

- Là một bộ đếm xuống 24 bit - có giá trị nạp vào tối đa là 2^24 -1

- Cứ sau một khoảng thời gian khi bộ đếm đếm về 0 thì sinh ra ngắt, dựa vào đó gọi một tác vụ xử lý ngắt

- Xung nhịp được lấy từ xung clock của lõi ARM

Công thức:

Interrupt period = (1 + SysTick_LOAD)/ Clock Frequence

Chu kỳ ngắt = (1 + Giá trị RELOAD)/ tần số xung nhịp

Trong đó giá trị lớn nhất của SysTick_LOAD = 2^24 -1 = 16777215

B : SƠ ĐÒ KHỐI VÀ MÃ NGUỒN BẬT TẮT LED BẲNG BUTTON

SƠ ĐỒ KHỐI:

Trang 6

MÃ NGUỒN : Bật tắt led bằng delay

#include <stdint.h>

#include "stm32l1xx.h"

uint32_t TimingDelay;

void GPIOB_Clock_Enable()

Trang 8

//NVIC_SetPriority (SysTick_IRQn, (1<< NVIC_PRIO_BITS)-1);

// Reset the SysTick counter value

SysTick->VAL = 0;

//Select processor clock

Trang 9

//1 = processor clock; 0 = external clock

SysTick->CTRL |= SysTick_CTRL_CLKSOURCE;//0x04

//Enable SysTick IRQ and SysTick Timer

SysTick->CTRL |= SysTick_CTRL_ENABLE;// 0x01

// Enables SysTick exception request

// 1 = counting down zero asserts the SysTick exception request

// 2 = counting down zero do not asserts the SysTick exception request

Trang 10

SysTick_Initialize(4194); // 4194 xung nhip

GPIOB->ODR &= ~(1<<6); // set pb 6 low

GPIOB->ODR |= 1<<7; // set pb 7 high

ECE 271 Microcomputer Architecture and Applications Lab 6: Pulse Width Modulation

Instructor: Prof Yifeng Zhu Spring 2015

Trang 11

PHẦN I : LÝ THUYẾT

- PWM (Pulse with modulation) - điều chế độ rộng xung :

- Là một kỹ thuật số đơn giản dùng để điều khiển giá trị của điện áp ra tải

- Sử dụng một xung chữ nhật ngắn để nhanh chóng bật tắt nguồn điện thế ON/ OFF, tạo giá trị điện

1 Prescaler : hệ số chia : có giá trị trong khoản từ 0 -> 65535

2 Counter modes : chế độ đếm - đếm tiến, đếm lùi hoặc nửa tiến nửa lùi

3 Counter period : chu kỳ đếm

Trang 16

//OC1M=110 for PMW Mode 1 output on channel 1

TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // OC1M = 110

TIM4->CCMR1 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2; // OC2M = 110

TIM4->CCMR1 |= TIM_CCMR1_OC1PE; //out put 1 preload enable- 0x0008

TIM4->CCMR1 |= TIM_CCMR1_OC2PE;

TIM4->CR1 |= TIM_CR1_ARPE; // reload preload enable - 0x0080

Trang 17

Auto-TIM4->CCER |= TIM_CCER_CC1E; // Enable output for channel 1- 0x001

Trang 18

// nTime : specifies the delay time length

Trang 19

TIM4->CCR2 = brightness_1; // Set brightness for chanel 2

for(i=0; i<1000; i++); // A short delay

Trang 20

//Configure GPIO pins

Trang 21

TIM4->PSC = 2097000/1000-1;

//Set the auto-reload value: upcounting (0->ARR), downcounting (ARR->0)

TIM4->ARR = 1000;

TIM4->CCR1 = 500;

//Set PWM mode 1 or mode 2 on chanel 1, channel 2

TIM4->CCMR1 |= TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1; //bit

Trang 22

+ Độ tiêu tốn năng lượng

Độ phân giải càng cao thì tốc độ thực của tín hiệu càng cao nhưng tốn nhiều bộ nhớ để lưu dữ liệu

- 3 chức năng chính:

+ Lấy mẫu : rời rạc hóa về mặt thời gian

+ Lượng tử hóa : rời rạc hóa trục biên độ

+ Mã hóa: chuyển mẫu sang mã nhị phân

Trang 23

Có ba thông số cơ bản :

1 Prescaler : hệ số chia : có giá trị trong khoản từ 0 -> 65535

2 Counter modes : chế độ đếm - đếm tiến, đếm lùi hoặc nửa tiến nửa lùi

3 Counter period : chu kỳ đếm

B : SƠ ĐÒ KHỐI VÀ MÃ NGUỒN

SƠ ĐỒ KHỐI:

Trang 24

Lập vô tận

Trang 25

// This code is for the book "Embedded Systems with ARM Cortex-M3

// Microcontrollers in Assembly Language and C, Yifeng Zhu,

Trang 26

// ISBN-10: 0982692625

// @attension

// This code is provided for education purpose The author shall not be

// held liable for any direct, indirect or consequential damages, for any

// reason whatever More information can be found from book website:

* STM32L1 Discovery Kit Pin Connections (STM32L152RBT6 or STM32L152RCT6)

* USER Pushbutton < -> PA.0 (clock: RCC_AHBENR_GPIOAEN)

* RESET Pushbutton < -> RESET

* Green LED (LD3) < -> PB.7 (clock: RCC_AHBENR_GPIOBEN)

* Blue LED (LD4) < -> PB.6 (clock: RCC_AHBENR_GPIOBEN)

* Touch Sensors < -> 6 pins, PA.6,7 (group 2), PB.0,1 (group 3), PC.4,5 (group 9)

* LCD (24 segments)< -> 28 pins, PA.1,2,3,8,9,10,15,

* PB.3,4,5,8,9,10,11,12,13,14,15

Trang 27

* PC.0,1,2,3,6,7,8,9,10,11

* ST Link < -> PA.13,14

* Boot 1 < -> PB.2

* Freely available pins: PA.5, PA.11, PA.12, PC.12, PD.2

* A GPIO pin is 5V tolerant and can sink or source up to 8 mA

************************************************************************

*********************************

*/

#define bool _Bool

volatile uint32_t TimingDelay = 0;

char buff[30];

void SysTick_Initialize(uint32_t ticks){

SysTick->CTRL = 0; // Disable SysTick IRQ and SysTick counter

RCC->ICSCR &= ~(0x07<<13); // Interrupt Control and State Register

RCC->ICSCR |= 0x06<<13; // Set MSIRANGE as 110 (4.194 Mhz)

RCC->CR |= 0x01<<8; // Set MSION

while(!(RCC->CR & (0x01<<9))); // Wait for MSIRDY

SysTick->LOAD = ticks - 1; // Set reload register

//NVIC_SetPriority(SysTick_IRQn, (1<< NVIC_PRIO_BITS) - 1);

Trang 29

void LCD_WriteChar(uint8_t* ch, bool point, bool colon, uint8_t position);

static void LCD_Conv_Char_Seg(uint8_t* c, bool point, bool colon, uint8_t* digit);

void LCD_DisplayStringScroll(uint8_t* ptr, bool direction, uint32_t delay); // My

function

void ADCInit(void); // My function

void LCD_Clock_Init(void){

RCC->APB1ENR |= RCC_APB1ENR_PWREN; // Power interface clock enable

PWR->CR |= PWR_CR_DBP; // Disable Backup Domain write protection

RCC->CSR |= RCC_CSR_RTCSEL_LSI; // LSI oscillator clock used as RTC clock

//LSI clock varies due to frequency dispersion

//RCC->CSR |= RCC_CSR_RTCSEL_LSE; // LSE oscillator clock used as RTC clock

RCC->CSR |= RCC_CSR_RTCEN; // RTC clock enable

/* Disable the write protection for RTC registers */

RTC->WPR = 0xCA; // RTC write protection register (WPR)

RTC->WPR = 0x53; // Write "0xCA" and "0x53" to unlock the write protection

// Wait until MSI clock ready

while((RCC->CR & RCC_CR_MSIRDY) == 0); // MSI Ready Flag is set by hardware

/* Enable comparator clock LCD */

RCC->APB1ENR |= RCC_APB1ENR_LCDEN;

Trang 30

RCC->AHBENR |= 0x01<<0; // Enable the clock to GPIO port A

RCC->AHBENR |= 0x01<<1; // Enable the clock to GPIO port B

RCC->AHBENR |= 0x01<<2; // Enable the clock to GPIO port C

//Set port A (pin 1,2,3,8,9,10,15), B (pin 3,4,5,8,9,10,11,12,13,14,15) and C (pin 0,1,2,3,6,7,8,9,10,11) as Alternative Function (AF)

GPIOA->MODER &= ~(0x03<<(2*1) | 0x03<<(2*2) | 0x03<<(2*3) |

0x03<<(2*8) | 0x03<<(2*9) | 0x03<<(2*10) | 0x03<<(2*15));

Trang 32

GPIOB->AFR[1] |= 0x0B<<(4*(8-8)) | 0x0B<<(4*(9-8)) | 0x0B<<(4*(10-8)) | 0x0B<<(4*(11-8)) | 0x0B<<(4*(12-8)) | 0x0B<<(4*(13-8)) | 0x0B<<(4*(14-8)) |

LCD->FCR &= ~LCD_FCR_PON;

Trang 33

LCD->FCR |= LCD_FCR_PON_0 | LCD_FCR_PON_1 | LCD_FCR_PON_2; // Set the pulse on period to 111

LCD->CR |= LCD_CR_MUX_SEG; // Enable the mux segment

LCD->CR &= ~LCD_CR_VSEL; // Select internal voltage as LCD voltage source

while((LCD->SR & LCD_SR_FCRSR) == 0); // Wait until FCRSF flag of LCD_SR is set

LCD->CR |= LCD_CR_LCDEN; // Enable the LCD

while((LCD->SR & LCD_SR_ENS) == 0); // Wait until the LCD is enabled

while((LCD->SR & LCD_SR_RDY) == 0); // Wait until the LCD booster is ready

}

void ADCInit(void){

RCC->CR |= RCC_CR_HSION; // Turn on HSI (High speed internal clock)

while((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait until HSI is ready

Trang 34

//RCC->AHBENR |= 0x01<<0; // Enable the clock to GPIO port A

GPIOA->MODER &= ~GPIO_MODER_MODER1;

GPIOA->MODER |= GPIO_MODER_MODER1_0 |

GPIO_MODER_MODER1_1; // Set pin 1 port A as analog

RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // Turn on the ADC clock

ADC1->CR2 &= ~ADC_CR2_ADON; // Turn off the ADC conversion

ADC1->SQR1 &= ~(0x1F<<20); // Set the length of the regular channel sequence to 1

ADC1->SQR5 &= ~ADC_SQR5_SQ1;

ADC1->SQR5 |= 0x01; // Set channel 1 as the first conversion in regular sequence

ADC1->SMPR3 &= ~ADC_SMPR3_SMP4; // Configure the sample time register for channel 1 as 4 cycles

ADC1->CR1 |= ADC_CR1_EOCIE; // Enable End-Of-Conversion interrupt

ADC1->CR2 |= ADC_CR2_CONT; // Enable continuous conversion mode

ADC1->CR2 &= ~ADC_CR2_DELS;

Trang 35

ADC1->CR2 |= ADC_CR2_DELS_0; // Configure delay selection as delayed until the coverted data have been read

NVIC_EnableIRQ(ADC1_IRQn); // Enable the interrupt of ADC1_IRQn in NVIC

NVIC_SetPriority(ADC1_IRQn, 5); // Configure the interrupt priority of ADC1_IRQn

ADC1->CR2 |= ADC_CR2_ADON; // Turn on the ADC conversion

ADC1->CR2 |= ADC_CR2_SWSTART; // Start the conversion of the regular channel

}

void ADC1_IRQHandler(void){ // ADC interrupt handler

if(ADC1->SR & ADC_SR_EOC){

// For a regular channel, check end of conversion (EOC) flag

sprintf(buff,"%d",ADC1->DR); // Save result on buff

LCD_DisplayString(buff);// show ADC result on lcd

Delay(200);

}

}

int main(void) {

Trang 36

void LCD_DisplayStringScroll(uint8_t* ptr, bool direction, uint32_t delay) {

// ptr is pointer to string we want to display

Trang 37

// direction = 1 if we want to scroll left to right and otherwise

// delay is the time between two scroll unit

LCD_Clear(); // Clear digits on LCD

for(i = 1; i <= 6; i++){ // Write to each digit of LCD

if(tptr+i-1 < endptr && tptr+i-1 >= ptr){ // If character we want to write is in range of string

LCD_WriteChar(tptr+i-1, 0, 0, i); // Write to LCD at position

i

}

}

Delay(delay); // Delay an amount of time

// If we scroll out of string, we start again Otherwise, increase or decrease tptr to make scroll effect

Trang 38

tptr = direction ? (tptr+5 == ptr ? endptr : tptr-1) : (tptr == endptr-1 ? ptr-6 : tptr+1);

}

}

void LCD_Clear(void) {

// Implement your code here

while ((LCD->SR & LCD_SR_UDR) != 0); // Wait for Update Display Request Bit

LCD->RAM[0] &= 0;

LCD->RAM[2] &= 0;

LCD->RAM[4] &= 0;

LCD->RAM[6] &= 0;

LCD->SR |= LCD_SR_UDR; // Set the Update Display Request

while ((LCD->SR & LCD_SR_UDD) == 0); // Wait for Update Display Done Bit

}

/* Macros used for set/reset bar LCD bar */

#define BAR0_ON t_bar[1] |= 8

#define BAR0_OFF t_bar[1] &= ~8

#define BAR1_ON t_bar[0] |= 8

#define BAR1_OFF t_bar[0] &= ~8

Trang 39

#define BAR2_ON t_bar[1] |= 2

#define BAR2_OFF t_bar[1] &= ~2

#define BAR3_ON t_bar[0] |= 2

#define BAR3_OFF t_bar[0] &= ~2

/* code for 'µ' character */

/* constant code for '*' character */

#define star 0xA0DD

/* constant code for '-' character */

#define C_minus 0xA000

/* constant code for '/' */

#define C_slatch 0x00c0

/* constant code for ° */

Trang 40

#define C_percent_1 0xec00

/* constant code for small o */

Trang 41

/* Constant table for cap characters 'A' > 'Z' */

const uint16_t CapLetterMap[26] = {

/* A B C D E F G H I */

Trang 42

/* Constant table for number '0' > '9' */

const uint16_t NumberMap[10] = {

/* 0 1 2 3 4 5 6 7 8 9 */

0x5F00,0x4200,0xF500,0x6700,0xEa00,0xAF00,0xBF00,0x04600,0xFF00,0xEF00

};

void LCD_WriteChar(uint8_t* ch, bool point, bool colon, uint8_t position) {

uint8_t digit[4]; /* Digit frame buffer */

// Convert displayed character in segment in array digit

LCD_Conv_Char_Seg(ch, point, colon, digit);

// Wait until LCD Ready */

while ((LCD->SR & LCD_SR_UDR) != 0); // Wait for Update Display Request Bit

switch (position) {

/* Position 1 on LCD (Digit 1)*/

Trang 43

LCD->RAM[0] |= ((digit[0]& 0x0c) << 26 ) | (digit[0]& 0x03) ; // 1G 1B 1M 1E

LCD->RAM[2] |= ((digit[1]& 0x0c) << 26 ) | (digit[1]& 0x03) ; // 1F 1A 1C 1D

LCD->RAM[4] |= ((digit[2]& 0x0c) << 26 ) | (digit[2]& 0x03) ; // 1Q 1K 1Col 1P

LCD->RAM[6] |= ((digit[3]& 0x0c) << 26 ) | (digit[3]& 0x03) ; // 1H 1J 1DP 1N

Trang 44

LCD->RAM[4] |= ((digit[2]& 0x0c) << 24 )|((digit[2]& 0x02) << 6 )|((digit[2]& 0x01) << 2 ) ; // 2Q 2K 2Col 2P

LCD->RAM[6] |= ((digit[3]& 0x0c) << 24 )|((digit[3]& 0x02) << 6 )|((digit[3]& 0x01) << 2 ) ; // 2H 2J 2DP 2N

Trang 45

LCD->RAM[4] &= 0xfff3efff;

LCD->RAM[6] &= 0xfff3efff;

LCD->RAM[0] |= ((digit[0]& 0x0c) << 16 ) | ((digit[0]& 0x03) << 12 ) ; // 5G 5B 5M 5E

Trang 46

LCD->RAM[2] |= ((digit[1]& 0x0c) << 16 ) | ((digit[1]& 0x03) << 12 ) ; // 5F 5A 5C 5D

LCD->RAM[4] |= ((digit[2]& 0x0c) << 16 ) | ((digit[2]& 0x01) << 12 ) ; // 5Q 5K 5P

LCD->RAM[6] |= ((digit[3]& 0x0c) << 16 ) | ((digit[3]& 0x01) << 12 ) ; // 5H 5J 5N

Trang 47

// Update the LCD display

// Set the Update Display Request

// Each time software modifies the LCD_RAM it must set the UDR bit to transfer the updated

// data to the second level buffer The UDR bit stays set until the end of the update and during

// this time the LCD_RAM is write protected

Ngày đăng: 04/02/2018, 17:54

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w