در قسمتهای قبلی با خود میکروکنترلر، معماری آن و نحوه پروگرام کردن آن آشنا شدیم، حال نوبت به راهاندازی پریفرالهای میکروکنترلر است در این قسمت ما خواندن و نوشتن بر روی پورتهای میکرو رو یاد میگیریم.
اگر با ساختار و کارکرد GPIO آشنایی ندارید پیشنهاد میکنم این دو آموزش در مورد GPIOها در STM32 رو ببینید.
آشنایی با ساختار I/O میکروکنترلر
اکثر موارد در عکس مشهود هست؛ ولی اگر بخواهیم ی توضیحی در مورد عکس بدیم به این صورت است که IOهای این میکرو دارای دیود محافظ، اشمیت تریگر و حالات برنامهپذیری پایه به شکلهای زیر هستند.
- Floating input
- Pull-up input
- Pull-down input
- Analog input
- Open-drain output
- Push-pull output
- Input and output of alternate function
و همچنین همه پایههای میکرو میتواند بهعنوان EXTI کانفیگ بشوند که در بخش وقفههای به آن میپردازیم.
برای فعالکردن هر پریفرالی از میکرو لازم است که به آن پریفرال کلاک برسد ما با استفاده از دستوارت زیر کلاک رو به پریفرالهای مختلف میرسانیم.
1 2 3 4 5 6 7 8 9 10 11 | //////////////////////////////////////////////////////////////////////////////////Clock GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //////////////////////////////////////////////////////////////////////////////////Clock GPIOB RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //////////////////////////////////////////////////////////////////////////////////Clock GPIOC RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); |
برای پیداکردن اینکه هر پریفرال GPIO به کدام شاخه کلاک متصل شدهاند میتواند از دیتاشیت کمک بگیرید.
همانطور که در عکس میبینید هر سه GPIO من در APB2 قرار دارند.
برای کانفیگ کردن GPIOها باید از استراکت GPIO_InitTypeDef استفاده بکنید. (باید به این نکته توجه بکنید که همه بخشهای میکرو توسط رجیسترها کنترل میشود پس “باید” در اینجا بهمنظور اینکه شما قادر نیستید به رجیستری برنامه بنویسید نیست.)
سپس به آن اسمی دلخواه نسبت دهید تا بتواند از محتویات درون استراکت استفاده نمایید.
به این صورت:
1 | GPIO_InitTypeDef SISOOG; |
ازاینپس شما با تایپکردن اسم دلخواه خودتان میتواند به محتویات استراکت دسترسی داشته باشید که برای این استراکت بهخصوص سه عدد است:
1 2 3 4 5 | GPIO_InitTypeDef SISOOG; SISOOG.GPIO_Mode = مود استفاده پین SISOOG.GPIO_Pin = شماره پایه SISOOG.GPIO_Speed = سرعت پایه |
پس از تنظیم مقادیر باید آنها را بر روی پریفرالGPIO اعمال کنیم که از تابع زیر کمک میگیریم.
1 | GPIO_Init(GPIOX,&SISOOG); |
بهجای GPIOX پورتی که میخواهیم تغییرات در آن اعمال شود را قرار میدهیم. برای مثال GPIOA
برای مود استفاده پین و سرعت پایه مقادیری از قبل تعریف شده که ما از آنها استفاده میکنیم.
حالا من میخواهم پایه 0 از GPIOA را هر یک ثانیه یک بار روشن و خاموش کنم.
اولازهمه کانفیگ رو انجام میدهیم به شکل زیر:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | GPIO_InitTypeDef GPIO_LED_STCT; GPIO_LED_STCT.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_LED_STCT.GPIO_Pin = LED_PIN; GPIO_LED_STCT.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA,&GPIO_LED_STCT); While(1) { GPIO_WriteBit(GPIOA,GPIO_Pin_0,1); Delay_Ms(1000); GPIO_WriteBit(GPIOA,GPIO_Pin_0,0); Delay_Ms(1000); } |
به این صورت ما توانستیم یک پایه رو خاموش و روشن کنیم.
برای خواندن از GPIO هم از تابع زیر کمک میگیریم.
1 | GPIO_ReadInputDataBit(KEY_GPIO,KEY_PIN) |
در اینجا یک پروژه تست آماده کردهام که از همه موارد بالا در آن استفاده شده است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | /********************************** (C) COPYRIGHT ******************************* * File Name : main.c * Author : WCH * Version : V1.0.0 * Date : 2021/06/06 * Description : Main program body. ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for * microcontroller manufactured by Nanjing Qinheng Microelectronics. *******************************************************************************/ /* *@Note USART Print debugging routine: USART1_Tx(PA9). This example demonstrates using USART1(PA9) as a print debug port output. */ #include "debug.h" /* Global typedef */ /* Global define */ #define DATA_PIN GPIO_Pin_0 #define CLK_PIN GPIO_Pin_1 #define LATCH_PIN GPIO_Pin_2 #define Shiftreg_GPIO GPIOB #define LED_PIN GPIO_Pin_0 #define LED_GPIO GPIOA #define KEY_PIN GPIO_Pin_0 #define KEY_GPIO GPIOC #define GPIO_8bit GPIOE void soft_shiftregister(uint8_t data); /* Global Variable */ char data=0; /********************************************************************* * @fn main * * @brief Main program. * * @return none */ int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); printf("SystemClk:%d\r\n",SystemCoreClock); printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() ); printf("This is printf example\r\n"); //////////////////////////////////////////////////////////////////////////////////Clock GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //////////////////////////////////////////////////////////////////////////////////Clock GPIOB RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //////////////////////////////////////////////////////////////////////////////////Clock GPIOC RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //////////////////////////////////////////////////////////////////////////////////Shift reg GPIO_InitTypeDef GPIO_SR; GPIO_SR.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_SR.GPIO_Pin = DATA_PIN|CLK_PIN|LATCH_PIN; GPIO_SR.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(Shiftreg_GPIO,&GPIO_SR); //////////////////////////////////////////////////////////////////////////////////LED Pin GPIO_InitTypeDef GPIO_LED_STCT; GPIO_LED_STCT.GPIO_Mode = GPIO_Mode_Out_PP; //Push Pull Cfg GPIO_LED_STCT.GPIO_Pin = LED_PIN; GPIO_LED_STCT.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(LED_GPIO,&GPIO_LED_STCT); //////////////////////////////////////////////////////////////////////////////////Key Input GPIO_InitTypeDef GPIO_KEY_STCT; GPIO_KEY_STCT.GPIO_Mode = GPIO_Mode_IPU; //INPUT PULL UP GPIO_KEY_STCT.GPIO_Pin = KEY_PIN; GPIO_Init(KEY_GPIO,&GPIO_KEY_STCT); //////////////////////////////////////////////////////////////////////////////////8 bit output GPIO_InitTypeDef GPIO_8bit_STCT; GPIO_8bit_STCT.GPIO_Mode = GPIO_Mode_Out_PP; //Push Pull Cfg GPIO_8bit_STCT.GPIO_Pin |= 0xff; GPIO_8bit_STCT.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIO_8bit,&GPIO_8bit_STCT); while(1) { if(GPIO_ReadInputDataBit(KEY_GPIO,KEY_PIN)==0) { data++; if(data>=100)data=0; soft_shiftregister(data); GPIO_Write(GPIO_8bit,(0xff&data)); } GPIO_WriteBit(GPIOA,GPIO_Pin_0,1); Delay_Ms(100); GPIO_WriteBit(GPIOA,GPIO_Pin_0,0); Delay_Ms(100) } } void soft_shiftregister(uint8_t data) { for(int ss=0;ss<8;ss++) { if(data)GPIO_WriteBit(Shiftreg_GPIO,DATA_PIN,1); else GPIO_WriteBit(Shiftreg_GPIO,DATA_PIN,0); GPIO_WriteBit(Shiftreg_GPIO,CLK_PIN,1); GPIO_WriteBit(Shiftreg_GPIO,CLK_PIN,0); data<<=1; } GPIO_WriteBit(Shiftreg_GPIO,LATCH_PIN,1); GPIO_WriteBit(Shiftreg_GPIO,LATCH_PIN,0); } |
امیدوارم که آموزش براتون مفید بوده باشه، به امید دیدار شما عزیزان تا آموزش بعدی.