SD card initialization using SPI os STM32

SD card initialization using SPI os STM32

Wątek przeniesiony 2020-10-01 16:35 z C/C++ przez Patryk27.

D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:58
0

Cześć. Próbuje odczytać plik z karty SD na mikrokontrolerze STM32 używając SPI i FatFS i mam problem z komendą ACMD41. Wcześniej komendy CMD0 i CMD8 działają prawidłowo i zwracają odpowiednie wartości, z których wnioskuję, że mam kartę typu v2. Następnie próbuje wysłać komendę ACMD41 0x01 więc wysyłam ją kolejny raz i wtedy w 16 cyklach dostaję odpowiedź 0xff co kończy inicjalizację błędem. Przejrzałem wiele stron z opisem obsługi kart SD przez SPI i wszędzie znajduję ten sam sposób więc nie wiem co u mnie jest nie tak. Sprawdzałem tęż gotową bibliotekę https://controllerstech.com/sd-card-using-spi-in-stm32/ i również dostaję error po tej komendzie. Próbowałem też to zrobić na 4 róznych kartach SD i na każdej dzieje się to samo.
Może ktoś będzie w stanie mi pomóc z tym problemem?

Kopiuj
    /*
     * sd_spi.c
     *
     *  Created on: 26.11.2017
     *      Author: jaras
     */
    
    #include "sd_spi.h"
    #include <string.h>
    
    uint8_t SDSPI_SendCMD(SPI_HandleTypeDef *phandle, uint8_t cmd, uint32_t arg, uint8_t crc) {
    	uint8_t buf[6];
    	buf[0] = cmd | 0x40;
    	buf[1] = (arg >> 24) & 0xff;
    	buf[2] = (arg >> 16) & 0xff;
    	buf[3] = (arg >> 8) & 0xff;
    	buf[4] = arg & 0xff;
    	buf[5] = crc;
    
    	if(HAL_SPI_Transmit(phandle, buf, 6, 1000) != HAL_OK) {
    		return 1;
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_Response(SPI_HandleTypeDef *phandle, uint8_t *buf, uint16_t size) {
    	uint8_t tx = 0xff;
    	uint8_t rx = 0xff;
    	uint8_t i = 0;
    
    	while(rx == 0xff) {
    		if(HAL_SPI_TransmitReceive(phandle, &tx, &rx, 1, 1000) != HAL_OK) {
    			return 1;
    		}
    		i++;
    		if(i > 8) {
    			return 2;
    		}
    	}
    
    	*buf = rx;
    
    	for(uint16_t k = 1; k < size; k++) {
    		if(HAL_SPI_TransmitReceive(phandle, &tx, &rx, 1, 1000) != HAL_OK) {
    			return 1;
    		}
    		*(buf + k) = rx;
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_CMD(SPI_HandleTypeDef *phandle, uint8_t cmd, uint32_t arg, uint8_t crc,
    					uint8_t *response, uint8_t size) {
    
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_RESET);
    
    	uint8_t res = SDSPI_SendCMD(phandle, cmd, arg, crc);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 1;
    	}
    
    	res = SDSPI_Response(phandle, response, size);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 2;
    	}
    
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    	uint8_t tx = 0xff;
    	if(HAL_SPI_Transmit(phandle, &tx, 1, 1000) != HAL_OK) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 3;
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_ACMD(SPI_HandleTypeDef *phandle, uint8_t cmd, uint32_t arg, uint8_t crc,
    					uint8_t *response, uint8_t size) {
    	uint8_t value0;
    
    	uint8_t rx = 0;
    
    	uint8_t res = SDSPI_CMD(phandle, 55, 0, 0x65, &rx, 1);
    	value0=rx;
    	if(res > 0) {
    		return 1;
    	}
    	if((rx & 0xf4) > 0) {
    		return 2;
    	}
    
    	res = SDSPI_CMD(phandle, cmd, arg, crc, response, size);
    	if(res > 0) {
    		return 3;
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_Init(SPI_HandleTypeDef *phandle) {
    	uint8_t value0;
    	uint8_t value1;
    	uint8_t value2;
    	uint8_t value3;
    	uint8_t value4;
    
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    	HAL_Delay(10);
    	uint8_t buf[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    	if(HAL_SPI_Transmit(phandle, buf, 10, 1000) != HAL_OK) {
    		return 1; //spi error
    	}
    
    	uint8_t res = SDSPI_CMD(phandle, 0, 0, 0x95, buf, 1);
    	value0 = buf[0];
    	if(res > 0) {
    		return 1; //command error
    	}
    	if(buf[0] != 1) {
    		return 2; //not initialized
    	}
    
    	uint8_t type = 0;
    	uint8_t block = 0;
    
    	res = SDSPI_CMD(phandle, 8, 0x01aa, 0x87, buf, 5);
    	value0 = buf[0];
    	value1 = buf[1];
    	value2 = buf[2];
    	value3 = buf[3];
    	value4 = buf[4];
    	if(res > 0) {
    		type = 1;
    	}
    	if(buf[0] != 1) {
    		type = 1;
    	}
    	if((buf[3] & 0x0f) != 1 || buf[4] != 0xaa) {
    		return 3; //initialization error
    	}
    
    	uint8_t stat = 0;
    	uint32_t tickstart = 0;
    
    	if(type == 0) {
    		stat = 1;
    		tickstart = HAL_GetTick();
    		while(stat > 0) {
    			if((HAL_GetTick()-tickstart) >= 1000) {
    				HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    				return 4; //timeout
    			}
    
    			res = SDSPI_ACMD(phandle, 41, 0x40000000, 0x77, &stat, 1);
    			if(res > 0) {
    				return 5; //not supported
    			}
    		}
    
    		res = SDSPI_CMD(phandle, 58, 0, 0x75, buf, 5);
    		if(res > 0) {
    			return 6; //not supported
    		}
    		if(buf[0] > 0) {
    			return 7;
    		}
    		if((buf[1] & 0x04) > 0) {
    			block = 1;
    		}
    
    	}
    	if(type == 1) {
    		stat = 1;
    		tickstart = HAL_GetTick();
    		while(stat > 0) {
    			if((HAL_GetTick()-tickstart) >= 1000) {
    				HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    				stat = 0;
    				type = 2;
    			}
    
    			res = SDSPI_ACMD(phandle, 41, 0, 0xff, &stat, 1);
    			if(res > 0) {
    				stat = 0;
    				type = 2;
    			}
    		}
    	}
    	if(type == 2) {
    		stat = 1;
    		tickstart = HAL_GetTick();
    		while(stat > 0) {
    			if((HAL_GetTick()-tickstart) >= 1000) {
    				HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    				return 8; //timeout
    			}
    
    			res = SDSPI_CMD(phandle, 1, 0, 0xff, &stat, 1);
    			if(res > 0) {
    				return 9; //error
    			}
    		}
    	}
    	if(block == 0) {
    		res = SDSPI_CMD(phandle, 16, 512, 0xff, buf, 1);
    		if(res > 0) {
    			return 10; //not supported
    		}
    		if(buf[0] > 0) {
    			return 11; //error
    		}
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_ReadCommand(SPI_HandleTypeDef *phandle, uint8_t cmd, uint32_t arg, uint8_t *buf, uint16_t size) {
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_RESET);
    
    	uint8_t stat = 0;
    	uint8_t res = SDSPI_SendCMD(phandle, cmd, arg, 0xff);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 1; //error
    	}
    
    	res = SDSPI_Response(phandle, &stat, 1);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 2; //error
    	}
    	if(stat > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 3; //error result
    	}
    
    	//wait for data token
    	uint32_t tickstart = HAL_GetTick();
    	uint8_t tx = 0xff;
    	stat = 0xff;
    	while(stat == 0xff) {
    		if((HAL_GetTick()-tickstart) >= 1000) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 4; //timeout
    		}
    		if(HAL_SPI_TransmitReceive(phandle, &tx, &stat, 1, 1000) != HAL_OK) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 5;
    		}
    	}
    
    	if(stat != 0xfe) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 6; //error token
    	}
    
    	//read sector
    	for(uint16_t i = 0; i < size; i++) {
    		if(HAL_SPI_TransmitReceive(phandle, &tx, buf +i, 1, 1000) != HAL_OK) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 7;
    		}
    	}
    
    	//read 2 byte crc
    	for(uint16_t i = 0; i < 2; i++) {
    		if(HAL_SPI_TransmitReceive(phandle, &tx, &stat, 1, 1000) != HAL_OK) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 7;
    		}
    	}
    
    	//end
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    	if(HAL_SPI_Transmit(phandle, &tx, 1, 1000) != HAL_OK) {
    		return 9;
    	}
    
    	return 0;
    }
    
    uint8_t SDSPI_WriteBlock(SPI_HandleTypeDef *phandle, uint32_t lba, uint8_t *buf, uint16_t size) {
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_RESET);
    
    	uint8_t stat = 0;
    	uint8_t res = SDSPI_SendCMD(phandle, 24, lba, 0xff);
    	if(res > 0) {
    		return 1; //error
    	}
    
    	res = SDSPI_Response(phandle, &stat, 1);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 2; //error
    	}
    	if(stat > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 3; //error result
    	}
    
    	//8 tics of CLK
    	stat = 0xff;
    	if(HAL_SPI_Transmit(phandle, &stat, 1, 1000) != HAL_OK) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 4;
    	}
    
    	//data packet
    	//data token
    	stat = 0xfe;
    	if(HAL_SPI_Transmit(phandle, &stat, 1, 1000) != HAL_OK) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 5;
    	}
    	//data block
    	if(HAL_SPI_Transmit(phandle, buf, size, 1000) != HAL_OK) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 6;
    	}
    	//crc
    	uint8_t crc[] = {0xff, 0xff};
    	if(HAL_SPI_Transmit(phandle, crc, 2, 1000) != HAL_OK) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 7;
    	}
    
    	//data response
    	res = SDSPI_Response(phandle, &stat, 1);
    	if(res > 0) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 8; //error
    	}
    	if((stat & 0x1f) != 0x05) {
    		HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    		return 9; //error result
    	}
    
    	//wait
    	uint32_t tickstart = HAL_GetTick();
    	uint8_t tx = 0xff;
    	stat = 0;
    	while(stat == 0) {
    		if((HAL_GetTick()-tickstart) >= 1000) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 10; //timeout
    		}
    		if(HAL_SPI_TransmitReceive(phandle, &tx, &stat, 1, 1000) != HAL_OK) {
    			HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    			return 11;
    		}
    	}
    
    	HAL_GPIO_WritePin(SDSPI_CSPORT, SDSPI_CSPIN, GPIO_PIN_SET);
    	return 0;
    }
    
    uint8_t SDSPI_ReadBlock(SPI_HandleTypeDef *phandle, uint32_t lba, uint8_t *buf, uint16_t size) {
    	return SDSPI_ReadCommand(phandle, 17, lba, buf, size);
    }
    
    uint8_t SDSPI_ReadInfo(SPI_HandleTypeDef *phandle, uint16_t *sector, uint32_t *capacity) {
    	uint8_t buf[16];
    	uint8_t res = SDSPI_ReadCommand(phandle, 9, 0, buf, 16);
    	if(res > 0) {
    		return res;
    	}
    
    	uint8_t version = buf[0] >> 6;
    	uint32_t c_size = 0;
    	uint8_t c_size_mult = 0;
    	uint8_t read_bl_len = 0;
    	if(version == 0) {
    		read_bl_len = buf[5] & 0x0f;
    		c_size = (((buf[6] & 3) << 16) | (buf[7] << 8) | buf[8]) >> 6;
    		c_size_mult = (((buf[9] & 3) << 8) | buf[10]) >> 7;
    		*sector = 1 << read_bl_len;
    		*capacity = (c_size +1) * (1 << (c_size_mult +2)) * (*sector);
    	}
    	else {
    		c_size = ((buf[7] & 0x3f) << 16) | (buf[8] << 8) | buf[9];
    		*sector = 512;
    		*capacity = (c_size +1) * 512 * 1024;
    	}
    	return 0;
    }
edytowany 4x, ostatnio: danielbr3
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
0

Na szybko bo z telefonu: porównaj z driverem stąd https://github.com/DISTORTEC/distortos

D3
Jest tutaj coś dotyczącego karty SD? nie mogę nic takiego znaleźć wśród tych plików
D3
Niestety ciężko się przegląda ten projekt, jest mocno rozbudowany i skakanie po ta wielu funkcjach sprawia, że w pewnym momencie się w tym gubie, sposób wysyłania tej komendy ACMD41 wydaje się jednak podobny
VT
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 2 lata
0

To fragment kodu, który u mnie działał na STM32F429. Oryginał wzięty z https://blog.domski.pl/wp-content/uploads/2016/01/sd_stm32.c plus parę moich poprawek z tego co pamiętam:

Kopiuj
// na podstawie: https://blog.domski.pl/wp-content/uploads/2016/01/sd_stm32.c
uint8_t sd_init3 (SPI_HandleTypeDef *phandle) 
{
	unsigned char i, cmd_arg[6];
	unsigned int Count = 0x1FFF;
	uint8_t n, ty, ocr[4];
	uint32_t tickstart;

	// czesc power_on()
	cs_sd(1);

	for (i = 0; i < 10; i++)
		xmit_spi(phandle, 0xFF);

	cs_sd(1);

	cmd_arg[0] = (CMD0 | 0x40);
	cmd_arg[1] = 0;
	cmd_arg[2] = 0;
	cmd_arg[3] = 0;
	cmd_arg[4] = 0;
	cmd_arg[5] = 0x95;

	for (i = 0; i < 6; i++)
		xmit_spi(phandle, cmd_arg[i]);

	while ((rcvr_spi(phandle) != 0x01) && Count)
		Count--;

	cs_sd(1);
	xmit_spi(phandle, 0xFF);

	// koniec power_on()

	// czesc disk_initialize()

	cs_sd(0);
	ty = 0;
	if (send_cmd(phandle, CMD0, 0) == 1) { /* Enter Idle state */
		//Timer1 = 100; /* Initialization timeout of 1000 msec */
		if (send_cmd(phandle, CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
			for (n = 0; n < 4; n++)
				ocr[n] = rcvr_spi(phandle);
			if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
				tickstart = HAL_GetTick();
				do {
					if ((send_cmd(phandle, CMD55, 0) <= 1) && (send_cmd(phandle, CMD41, 1UL << 30) == 0))
						break; /* ACMD41 with HCS bit */
				} while (HAL_GetTick() - tickstart < 1000);		// czekaj max 1 sekunde
				
				if ((HAL_GetTick() - tickstart < 1000) && send_cmd(phandle, CMD58, 0) == 0) { /* Check CCS bit */
					for (n = 0; n < 4; n++)
						ocr[n] = rcvr_spi(phandle);
					ty = (ocr[0] & 0x40) ? 6 : 2;
				}
			}
		} else { /* SDC Ver1 or MMC */
			ty = ((send_cmd(phandle, CMD55, 0) <= 1) && (send_cmd(phandle, CMD41, 0) <= 1)) ? 2 : 1; /* SDC : MMC */
			tickstart = HAL_GetTick();
			do {
				if (ty == 2) {
					if ((send_cmd(phandle, CMD55, 0) <= 1) && (send_cmd(phandle, CMD41, 0) == 0))
						break; /* ACMD41 */
				} else {
					if (send_cmd(phandle, CMD1, 0) == 0)
						break; /* CMD1 */
				}
			} while (HAL_GetTick() - tickstart < 1000);		// czekaj max 1 sekunde
			if ((HAL_GetTick() - tickstart >= 1000) || send_cmd(phandle, CMD16, 512) != 0) /* Select R/W block length */
				ty = 0;
		}
	} else printf("else1\r\n");
	//CardType = ty;
	cs_sd(1);
	rcvr_spi(phandle); /* Idle (Release DO) */

	return 0;
}

cs_sd(0/1) - procedura, która kasuje/ustawia stan sygnału Slave Select.

edytowany 1x, ostatnio: vtx
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)