Арифметика странного указателя в цикле for в C

Я программирую msp430 с IAR EBW.

Я получил выражение следующим образом:

adres = (uint_fast16_t *) 0x8602 + (0x0200*i);

в цикле, так что я увеличивается с каждым циклом. По какой-то причине он пропускает каждый из двух адресов и дает мне:

0x8602
0x8A02
0x8E02

и так далее. Таким образом, 0x8802 пропускается, как 0x8C02 и так далее.

Почему это происходит?

//// ниже приведен полный код, обратите внимание, что я размещен в трех циклах, и каждый дает одинаковый результат. //// отметим также, что при проверке во время отладки он показывает как: 1,2,3... и т. д.

#include "io430.h"
#include <stdint.h>

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  // Inicjalizuj piny GPIO
  P3OUT &= ~(BIT4+BIT5);        // zeruj wartości by zapobiec krótkotrwałym impulsom
  P3DIR |= BIT4; // ustaw pin3.4 UCA0TXD oraz piny 3.0 CS, 3.1 SIMO, 3.3 CLK jako wyjście
  P3DIR &= ~(BIT5);               // ustaw pin3.5 UCA0RXD oraz 3.2SOMI jako wejście
  P3SEL |= BIT4+BIT5;         // daj funkcje TXD i RXD pinom 3.4 i 3.5, funkcje SIMO,SOMI,CLK pinom 3.1,3.2,3.3

  // Inicjalizuj ustawienia zegarów BCS
  BCSCTL1 = CALBC1_16MHZ;       // ustawia DCO na 16MHz, wyłącz XT2, LFXT1 w trybie niskiej częstotliwości
  DCOCTL = CALDCO_16MHZ;        // ustawia DCO na 16MHz
  BCSCTL2 |= BIT2;              // ustawia dzielnik SMCLK na 4

  // Ustaw flash na czyszczenie segmentów
  while(FCTL3&BIT0);            // czekaj aż będzie można inicjalizować
  FCTL2 = FWKEY + BIT6 + BIT5+BIT3+BIT2; // ustawia źródło zegara na MCLK oraz jego dzielnik dający f = 363 kHz
  FCTL1 = FWKEY + BIT1;         // czyść indywidualne segmenty
  FCTL3 = FWKEY;            // zdejmuje blokadę na pisanie i czyszczenie (tu segmentów)

  // Czyść segmenty  
  uint_fast16_t *adres;
  uint_fast8_t i=0;
  for ( i=0 ; i < 59; i++)
    {
      adres = (uint_fast16_t *) 0x8602 + i*0x0200; // ustawia wskaźnik na kolejne miejsa w pamięci. sprawdzić!!
      *adres = 0;               // wyczyść segment przez wpisanie w jego komórkę głupiego bitu
      while(FCTL3&BIT0);        // poczekaj aż generator czasowy dla flasha
    }
  FCTL1 = FWKEY;                // blokuje możliwość czyszczenia

  __delay_cycles(65000);

  // Ustaw flash na zapis danych
  while(FCTL3&BIT0);            // czekaj aż będzie można pisać
  FCTL1 = FWKEY + BIT6;         // pozwól pisać do flash

  // Pisz do flash
  uint_fast16_t szesnastka = 0;

  for ( i=0 ; i < 59; i++)
    {
      szesnastka = (0x55 << 8 ) | 0xF0;
      adres = (uint_fast16_t *) 0x8602 + (0x0200*i); // ustawia wskaźnik na kolejne miejsa w pamięci. sprawdzić!!
      *adres = szesnastka;               // wyczyść segment przez wpisanie w jego komórkę głupiego bitu
      while(FCTL3&BIT0);        // poczekaj aż generator czasowy dla flasha
    }
  FCTL1 = FWKEY;                // blokuje możliwość pisania
  FCTL3 = FWKEY + LOCK;         // ustawia blokadę na pisanie i czyszczenie


  __delay_cycles(65000);


  // Inicjalizuj ustawienia do transmisji UART
  UCA0CTL0 = 0x00;              // ustawia domyślne parametry protokołu
  UCA0CTL1 |= BIT7+BIT6;        // ustawia źródło sygnału na SMCLK
  UCA0BR0 = 0xA0;               // ustawia dzielnik 4MHz do baud rate 9600
  UCA0BR1 = 0x01;               // ustawia dzielnik 4MHz do baud rate 9600                  
  UCA0MCTL |= BIT2+BIT3;        // ustawia modulacje zegara do baud rate 9600

  UCA0CTL1 &= ~UCSWRST;         // włącza maszynę USCI

  uint8_t *ptr;

  // Wyślij wszystkie wyniki poprzez UART
  for( i=0 ; i < 59 ; i++  )
  {
  ptr = (uint8_t *) 0x8602 + i*0x0200; // ustawia wskaźnik na kolejne miejsa w pamięci. 
  while(!(IFG2&UCA0TXIFG));   // czeka na możliwość wysłania
  UCA0TXBUF = *ptr;         // wysyła dane przez UART

  ptr++;
  while(!(IFG2&UCA0TXIFG));   // czeka na możliwość wysłania
  UCA0TXBUF = *ptr;         // wysyła dane przez UART
  }


  return 0;
}

4 ответа

Вы приводите первое значение как указатель к 16-битным значениям, поэтому добавление 0x200 собирается переместить его вперед на 512 16-битных (или 2-байтовых) значений.

Если вы сделали:

adres = (uint_fast32_t *) 0x8602 + (0x0200 * i ) ;

Это сделало бы:

0x8602
0x8E02
0x9202

Либо масштабируйся наполовину, либо делай математику перед броском:

adres = ( uint_fast16_t *) ( 0x8602 + ( 0x0200 * i ) ) ;

Это арифметика указателей, а не целочисленная математика.

Как i приращения, (uint_fast16_t *) 0x8602 + (0x0200*i) идет вверх 0x0200*2 как sizeof(uint_fast16_)в данном случае - 2.

Когда вы добавляете указатель, вы добавляете размер типа указателя к указателю, с которым вы работаете. Так, например, добавив 1 к char* добавит 1, и добавив 1 к uint32_t* добавлю 4.

Поэтому я думаю, что ваш код может работать так, как вы ожидаете, если вы измените его на:

adres = (uint_fast16_t *) ((char*)0x8602 + (0x0200*i));

Вы увеличиваете указатель uint_fast16* на 0x0200*i.

Когда вы добавляете к указателю, он увеличивается на размер базового типа, так что вы увеличиваете на 2 байта * 0x0200*i, а не только 0x0200 * i

Другие вопросы по тегам