- Tần số Clock đầu vào sử dụng là 8MHz.. - Hạn chế: Muốn thay đổi tần số phát ra cũng như độ rộng xung, ta phải khai báo lại trong code ở phần define.. - Máy được mô phỏng bằng phần mềm
Trang 1HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
BÁO CÁO BÀI TẬP LỚN
Môn học: HỆ THỐNG NHÚNG
Giảng viên hướng dẫn : Nguyễn Ngọc Minh
Sinh viên thực hiện :Nguyễn Đức Hiệp-B18DCDT071
Nguyễn Văn Cường-B18DCDT022
Lê Ngọc Sơn-B18DCDT204 Nguyễn Kính Đảm-B18DCDT039
Hà Nội
Trang 2
- -Thiết kế máy phát tần số sử dụng PWM từ 1Hz - 1000Hz
và hiển thị giá trị lên 4 con led 7 thanh.
1.Tổng quan
- Máy cho ra tần số đầu ra từ 1Hz đến 1000Hz, độ rộng xung từ 0% đến 100%
- Tần số đầu ra sẽ được hiển thị lên 4 chiếc LED 7 đoạn.
- Tần số Clock đầu vào sử dụng là 8MHz.
- Hạn chế: Muốn thay đổi tần số phát ra cũng như độ rộng xung, ta phải khai báo lại trong code ở phần define.
- Máy được mô phỏng bằng phần mềm Proteus.
2 Code
#include "stm32f10x.h" // Device header
#include "stm32f10x_rcc.h" // Keil::Device:StdPeriph Drivers:RCC
#include "stm32f10x_gpio.h" // Keil::Device:StdPeriph Drivers:GPIO
#include "stm32f10x_tim.h" // Keil::Device:StdPeriph Drivers:TIM
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
#define LED7SEG_A GPIO_Pin_0
#define LED7SEG_B GPIO_Pin_1
#define LED7SEG_C GPIO_Pin_2
#define LED7SEG_D GPIO_Pin_3
#define LED7SEG_E GPIO_Pin_4
#define LED7SEG_F GPIO_Pin_5
Trang 3#define LED7SEG_G GPIO_Pin_6
#define LED7SEG_DP GPIO_Pin_7
#define LED1 GPIO_Pin_1
#define LED2 GPIO_Pin_2
#define LED3 GPIO_Pin_3
#define LED4 GPIO_Pin_4
#define PORT_LED7SEG_CODE GPIOC
#define PORT_LED GPIOB
#define PORT_LED7SEG_CODE_CLOCK RCC_APB2Periph_GPIOC
#define PORT_LED_CLOCK RCC_APB2Periph_GPIOB
#define F (100)
#define PW (0.66)
uint16_t LED7SEG[10]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void TIM_PWM_Configuration(void);
void GPIO_Config(void);
void Delay(uint32_t);
int main (void){
SystemInit();
SystemCoreClockUpdate();
GPIO_Config();
TIM_PWM_Configuration();
//TIM1->CCR1 = 50 * ((10000/F) / 100); //50% Duty cycle
GPIO_ResetBits(PORT_LED, LED1); //LED1 = 0;
GPIO_ResetBits(PORT_LED, LED2); //LED2 = 0;
GPIO_ResetBits(PORT_LED, LED3); //LED1 = 0;
GPIO_ResetBits(PORT_LED, LED4); //LED2 = 0;
while(1)
{
for(uint8_t j = 0; j < 30; j++) {
GPIO_ResetBits(PORT_LED, LED2);
GPIO_ResetBits(PORT_LED, LED3);
GPIO_ResetBits(PORT_LED, LED4);
Trang 4GPIO_Write(PORT_LED7SEG_CODE, LED7SEG[F/1000]);
GPIO_SetBits(PORT_LED, LED1);
Delay(1);
GPIO_ResetBits(PORT_LED, LED1);
GPIO_ResetBits(PORT_LED, LED3);
GPIO_ResetBits(PORT_LED, LED4);
GPIO_Write(PORT_LED7SEG_CODE, LED7SEG[(F
%1000)/100]);
GPIO_SetBits(PORT_LED, LED2);
Delay(1);
GPIO_ResetBits(PORT_LED, LED1);
GPIO_ResetBits(PORT_LED, LED2);
GPIO_ResetBits(PORT_LED, LED4);
GPIO_Write(PORT_LED7SEG_CODE, LED7SEG[(F
%1000%100)/10]);
GPIO_SetBits(PORT_LED, LED3);
Delay(1);
GPIO_ResetBits(PORT_LED, LED1);
GPIO_ResetBits(PORT_LED, LED2);
GPIO_ResetBits(PORT_LED, LED3);
GPIO_Write(PORT_LED7SEG_CODE, LED7SEG[F
%1000%100%10]);
GPIO_SetBits(PORT_LED, LED4);
Delay(1);
} }
}
void Delay(uint32_t t)
{
unsigned int i,j;
for(i=0;i<t;i++){
for(j=0;j< 0x2AFF/10; j++);
}
}
void GPIO_Config()
{
Trang 5GPIO_InitTypeDef GPIO_InitStructure;
/*enble clock for GPIOC*/
RCC_APB2PeriphClockCmd(PORT_LED7SEG_CODE_CLOCK|
PORT_LED_CLOCK, ENABLE);
/*Configuration GPIO pin*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = LED7SEG_A|LED7SEG_B|LED7SEG_C| LED7SEG_D|LED7SEG_E|LED7SEG_F|LED7SEG_G|LED7SEG_A|
LED7SEG_DP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(PORT_LED7SEG_CODE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED1|LED2|LED3|LED4;
GPIO_Init(PORT_LED, &GPIO_InitStructure);
}
void TIM_PWM_Configuration(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 160 - 1; // ftimer = 50000Hz
TIM_TimeBaseStructure.TIM_Period = (50000/F); // So chu ki dem TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode =
TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_Pulse = PW*(50000/F); // Do rong xung TIM_OC1Init(TIM1, &TIM_OCInitStructure);
Trang 6TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
3 Giải thích code
- Để khai báo tần số đầu ra và độ rộng xung, ta chỉnh sửa
đoạn define
#define F (100)
#define PW (0.66)
Trong đó F là tần số và PW là độ rộng xung Trong ví dụ trên tần số đầu ra là 100Hz và độ rộng xung 66%.
- Tiếp theo, ta đi cấu hình cho PWM.
void TIM_PWM_Configuration(void)
+ Máy sử dụng Timer 1, tần số đầu ra tại Pin 8 _ Port A + Bộ chia tần (prescaler) = 160 – 1 Tần số của timer được chia từ tần số clock đầu vào qua bộ chia tần.
Ftimer = 8MHz/160 = 50000Hz
Trang 7+ Như vậy chu kì của Timer sẽ vào khoảng 1/Ftimer Để tạo
ra 1 tần số F chu kì 1/F, ta phải đếm 1 số lượng chu kì của timer bằng:
Period = (1/F)/(1/Ftimer) = Ftimer/F = 50000/F.
TIM_TimeBaseStructure.TIM_Prescaler = 160 - 1; // ftimer = 50000Hz
TIM_TimeBaseStructure.TIM_Period = (50000/F); // So chu ki dem
+ Độ rộng xung được khai báo là PW
TIM_OCInitStructure.TIM_Pulse = PW*(50000/F); // Do rong xung
+ Cuối cùng ta enable cho tín hiệu đầu ở Timer 1:
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
+ Như vậy máy đã tạo được một tần số đầu ra bằng F và có
độ rộng xung bằng PW.
- Hiển thị tần số đầu ra trên 4 chiếc LED 7 thanh.
+ Trước tiên ta cấu hình các chân đầu ra cho bộ LED 7 thanh
GPIO_Config();
+ Các chân đầu ra được khai báo trên phần define.
+ Sử dụng một hàm delay tương đối trong việc quét LED.
void Delay(uint32_t t);
+ Để hiển thị các số lên LED 7 thanh ta sử dụng bộ mã BCD.
uint16_t LED7SEG[10]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
+ LED1 được sử dụng để hiện chữ số hàng nghìn: F/1000
Trang 8+ LED2 hiển thị chữ số hàng trăm: (F%1000)/100
+ LED3 hiển thị chữ số hàng chục: (F%1000%100)/10
+ LED4 hiển thị chữ số hàng đ.vị : F%1000%100%10
+ Dùng 1 vòng lặp vô hạn để hiển thị Ví dụ hiển thị chữ số hàng nghìn
GPIO_ResetBits(PORT_LED, LED2);
GPIO_ResetBits(PORT_LED, LED3);
GPIO_ResetBits(PORT_LED, LED4);
GPIO_Write(PORT_LED7SEG_CODE, LED7SEG[F/1000]); GPIO_SetBits(PORT_LED, LED1);
Delay(1);
Tắt các LED 2, 3, 4 Mã LED đầu ra = F/1000 và bật LED1 Delay(1) sau đó tắt LED1, bật LED2 hiện số hàng trăm…
4 Kết quả thu được
+ Mô phỏng proteus.
Trang 9+ F = 1 và PW = 0.5 => T = 1s.
+ F = 10 và PW = 0.25 => T = 100 ms = 0.1s
Trang 10+ F = 100 và PW = 0.66 => T = 10 ms = 0.01s.
+ F = 1000 và PW = 0.75 => T = 1 ms = 0.001s.
Trang 11+ F = 222 và PW = 0.22 => T = 4.45 ms = 0.00445s