如何在ARM Cortex M4 TM4C123G微控制器中使用GPIO端口控制(GPIOPCTL)?

问题描述 投票:0回答:2

我正在尝试将超声波传感器与 ARM Cortex M4 MCU 连接。由于我正在使用边沿触发定时器来计算传感器回波的上升沿和下降沿之间的时间,我应该分配给回波输入引脚的备用功能是什么? 我在 http://cortex-m.com/tm4c-lessons/:

上找到了以下配置
void Timer0_init(void)
{
SYSCTL->RCGCTIMER |=(1U<<0); 
SYSCTL->RCGCGPIO |=(1U<<1); 
GPIOB->DIR &=~ECHO;
GPIOB->DEN |=ECHO;
GPIOB->AFSEL |=ECHO;
GPIOB->PCTL &=~0x0F000000;
GPIOB->PCTL |= 0x07000000;
TIMER0->CTL &=~1;
TIMER0->CFG =4;
TIMER0->TAMR = 0x17;
TIMER0->CTL |=0x0C;
TIMER0->CTL |=1;
}

我使用数据表来理解每一行,但对于我不理解的行:

GPIOB->PCTL &=~0x0F000000;
GPIOB->PCTL |= 0x07000000;

我猜第一行只是复位,第二行选择外围功能,但我无法理解或找不到在PCTL寄存器中将他用于输入的引脚设置为7的作用是什么?

c arm embedded robot
2个回答
4
投票

如第 688f 页的数据表中所述,该寄存器的使用位

27:24
用于设置在引脚 6 上使用的备用功能。根据
GPIOB->PCTL
,配置的引脚为 PB6。

现在您可以在第 1351 页的表 23-5 中看到设置了哪些备用功能。在这种情况下,它是

T0CCP0
,它是一个 pwm、一个捕获或一个基于引脚方向和外设配置的比较功能。

GPIOB->PCTL &=~0x0F000000;
用于重置引脚 6 功能,无需触及其他引脚。

GPIOB->PCTL |= 0x07000000;
设置引脚 6 功能,不更改其他引脚。


0
投票
#include "TM4C123.h"                    

#define GPIO_PORTA_CLOCK_EN 0x01 
#define GPIO_PORTA_AFSEL_DS 0x00 
#define GPIO_PA4_TRIG 0x10      
#define GPIO_PORTB_CLOCK_EN 0x02 
#define GPIO_PORTB_AFSEL_EN 0x20 
#define GPIO_PORTB_PCTL_CCP 0x00700000 
#define GPIO_PB6_ECHO 0x20          

#define GPIO_PORTF_CLOCK_EN 0x20
#define GPIO_PORTF_AFSEL_DS 0x00
#define GPIO_PORTF_PIN1_3_EN 0x0E
#define GPIO_PORTF_PIN1_3_OP 0x0E 
unsigned volatile long j;
uint32_t highEdgeCount, lowEdgeCount, cmDistance, distanceValue;
const double _1clock_16MHz = 62.5e-9;
const double factor = 5882;
void PA4_Digital_Output_Init(void);
void PB6_as_T0CCP0_Init(void);
void timer0_Init(void); 
void PF3_Digital_Output_Init(void);
void timer1A_uSec_Delay(uint32_t uDelay);
uint32_t distance_measurement(void);


int main(){
PA4_Digital_Output_Init();
PB6_as_T0CCP0_Init();
timer0_Init();
PF3_Digital_Output_Init();
while(1){
    distanceValue = distance_measurement();
    if (distanceValue<=10){
        GPIOF->DATA = 0x00;
        GPIOF->DATA ^= 0x01;
    } // red LED
    else if (distanceValue<=15&&distanceValue>=10){
        GPIOF->DATA = 0x00;
        GPIOF->DATA ^= 0x02;} // blue LED
    else if (distanceValue>=15)
    {
        GPIOF->DATA = 0x00;
        GPIOF->DATA ^= 0x08; 
        // green LED
    }
}
}

void PA4_Digital_Output_Init(void){

SYSCTL->RCGCGPIO |= GPIO_PORTA_CLOCK_EN;
for (j =0; j < 3 ; j++)     
GPIOA->AFSEL |= GPIO_PORTA_AFSEL_DS;

GPIOA->DEN |= GPIO_PA4_TRIG; // Digital enable for PA4

GPIOA->DIR |= GPIO_PA4_TRIG; // PA4 as output
}

void PB6_as_T0CCP0_Init(void){

SYSCTL->RCGCGPIO |= (1U<<1);
//SYSCTL->RCGCGPIO |= GPIO_PORTB_CLOCK_EN;
for (j =0; j < 3 ; j++)     

GPIOB->AFSEL |= GPIO_PORTB_AFSEL_EN;


GPIOB->DEN |= GPIO_PB6_ECHO; 

GPIOB->DIR &= ~GPIO_PB6_ECHO; // PB6 as input   ------------------

GPIOB->PCTL &= ~0x00F00000; 
GPIOB->PCTL |= GPIO_PORTB_PCTL_CCP;
}

void PF3_Digital_Output_Init(void){
// Step 1: Clock enable on PortF
SYSCTL->RCGCGPIO |= GPIO_PORTF_CLOCK_EN;
for (j =0; j < 3 ; j++)     // at least 3 clock cyles

// Step 2: APB is selected for PortF by selecting
// 0x40025000 as Base Address in DATA section

// Step 3: Disable alternate functionality on PortF
GPIOF->AFSEL |= GPIO_PORTF_AFSEL_DS;

// Step 4: Enable digital pin functionaliy on PortF pin 3
GPIOF->DEN |= GPIO_PORTF_PIN1_3_EN; // Digital enable for PF3

// Step 5: Set PortF pin 3 as an output pin
GPIOF->DIR |= GPIO_PORTF_PIN1_3_OP; // PF3 as output
}

void timer0_Init(void){

// Step 1: Enable Timer Clock on timer0
SYSCTL->RCGCTIMER |= (1U<<0);       // b 0000 0001
//SYSCTL->RCGCTIMER |= 0x01;        // b 0000 0001
for (j =0; j < 3 ; j++)     // at least 3 clock cyles

// Step 2: Ensure Timer is disabled before making any changes
TIMER0->CTL &= ~1;                  // TAEN = 0, i.e., timer0A is disabled
//TIMER0->CTL = 0x00;                   // TAEN = 0, i.e., timer0A is 
disabled

// Step 3: Select Mode of Operation of timer0 (Split/cancatenated/RTC)
TIMER0->CFG = 0x04;                 // timer0 is used as a 16-bit (split) 
timer, i.e., timer0A
TIMER0->TAMR = 0x17;                // TAMR = 3 (capture), TACMR = 1 (edge 
time count) TACDIR = 1 (count-up)

// Step 4: Set counter value limit, comparted to TAR to determine match 
event
//TIMER0->TAMATCHR = 0xFFFF;        // 
//TIMER0->TAPMR = 0xFF;     // used with TAMATCHR to expand to 0xFFFFFF 
with 8-bit prescaler (bit 16:23)

// Step 5: Interrupt configurations
TIMER0->ICR = 0x01;                 // Clear timer status flag (TATORIS, 
TATOMIS)

// Step 6: Enable the Timer and start counting
TIMER0->CTL |= 0x0C;                    // enable both edge count
TIMER0->CTL |= 0x01;                    // TAEN = 1
}

void timer1A_uSec_Delay(uint32_t uDelay){

// Step 1: Enable Timer Clock on timer1
SYSCTL->RCGCTIMER |= 0x02;      // b 0000 0010
for (j =0; j < 3 ; j++)     // at least 3 clock cyles

// Step 2: Ensure Timer is disabled before making any changes
TIMER1->CTL = 0x00;                 // TAEN = 0, i.e., timer1A is disabled

// Step 3: Select Mode of Operation of timer1 (Split/cancatenated/RTC)
TIMER1->CFG = 0x04;                 // timer1 is used as a 16-bit (split) 
timer, i.e., timer1A
TIMER1->TAMR = 0x02;                // TAMR = 2 (periodic), TACDIR = 0 
(count-down)

// Step 4: Load counter start value in Interval Load Register
TIMER1->TAILR = 16 - 1;     // for 16 MHz, 16 will generate 1 uSec delay

// Step 5: Interrupt configurations
TIMER1->ICR = 0x01;                 // Clear timer status flag (TATORIS, 
TATOMIS)

// Step 6: Enable the Timer and start counting
TIMER1->CTL |= 0x01;                    // TAEN = 1

// One iteration of this loop generates 1 micro-second delay
for(uint32_t i = 0; i<uDelay; i++){
    // Step 7: Poll TATORIS (Time-Out Raw Interrupt Status) bit to check 
timer1A timeout
    while((TIMER1->RIS & 0x01)==0); // Wait for timeout flag to set
    
    // After time-out, timer relaoads automatically and start counting
    // Clear timer status flag i.e., TATORIS flag
    TIMER1->ICR = 0x01;
}
// Disable Timer 
TIMER1->CTL = 0x00;         // TAEN = 0, i.e., timer1A is disablled}

uint32_t distance_measurement(void){
// Send a pulse at Sensor Trig Pin
GPIOA->DATA &= ~GPIO_PA4_TRIG;
timer1A_uSec_Delay(10);
GPIOA->DATA |= GPIO_PA4_TRIG;
timer1A_uSec_Delay(10);
GPIOA->DATA &= ~GPIO_PA4_TRIG;

// Capture 1st edge (rising edge)
TIMER0->ICR = 0x04;             // clear timer capture flag (i.e., CAECINT 
= 0)
while((TIMER0->RIS & 0x04) == 0);   // Wait till captured, by wait for bit 
to turn high
highEdgeCount = TIMER0->TAR;        // time at which last edge event took 
place

// Capture 2nd edge (falling edge)
TIMER0->ICR = 0x04;
while((TIMER0->RIS & 0x04) == 0);
lowEdgeCount = TIMER0->TAR;

cmDistance = lowEdgeCount - highEdgeCount;
cmDistance = _1clock_16MHz*(double)factor*(double)cmDistance;

return cmDistance;}

我也在使用超声波传感器,但使用的是 pb5,不用担心评论,任何人都可以告诉我为什么我的代码不起作用

© www.soinside.com 2019 - 2024. All rights reserved.