[C] Jak zmieniać poszczególne piny DS89C430
[C] Jak zmieniać poszczególne piny DS89C430
Zrobiłem płytkę zgodnie z tym artykułem i bawię się programowaniem DS89C430, programy kompiluję przy pomocy uC51 i mam całkowicie podstawowe pytanie: jak odwołać się do jednego bitu w porcie P1. Np. ustawić 1 na drugim pinie nie zmieniając przy tym pozostałych pinów portu?
Nie wiem czy u Ciebie tak samo, ale w przypadku AVR-ów robi się to przez odczyt stanu całego portu i wykonanie operacji OR lub AND z liczbą mającą jedynkę lub zero w miejscu interesującego Cię bitu, a następnie wrzucenie wyniku z powrotem na port. Czyli chcąc ustawić na jedynkę pin 2 portu A robiszTo ustawia trzeci bit portu na 1 nie zmieniając pozostałych. Zerowanie tego pinu wygląda takZamiast 0b11111011 możesz wstawić ~0b00000100. W avr-gcc służą do tego funkcje sbi i cbi i one właśnie tak są zdefiniowane:Dopiero zaczynam zabawę z C więc, jeśli jestem w błędzie to niech mnie ktoś poprawi 
Kod: Zaznacz cały
PORTA |= 0b00000100;Kod: Zaznacz cały
PORTA &= 0b11111011;Kod: Zaznacz cały
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))Możesz przecież zapisać tą samą liczbę szesnastkowo albo nawet dziesiętnie
Co prawda obejście problemu a nie rozwiązanie, ale działa
Możesz też chyba użyć przesunięcia bitowego w lewo. Pisząc 1<<n dostaniesz liczbę w której w zapisie binarnym będzie jedna jedynka na n-tym bicie (licząc od 0). Więc zapis 1<<3 da Ci w wyniku wartość 0b00001000. Więc jeśli chcesz ustawić na 1 piąty bit (licząc od 0) w porcie B to robisz:Nie mam tylko pewności czy to zadziała 
Kod: Zaznacz cały
PORTB |= (1<<5);Ach litości....AVR i '51 są do siebie pod kątem prostym....nie mieszajcie tego.c4r0 pisze:Nie wiem czy u Ciebie tak samo, ale w przypadku AVR-ów
Skoro jakoś zmęczyłeś jeden mój tekst, to może zmęczysz i drugi...
https://elportal.pl/index.php?module=Co ... y&ceid=234
pobierz sobie pliki źródłowe: https://elportal.pl/tasza/vfd-clk/vfd-clk-sources.zip
w pliku vfd_clk.c poszukaj odwołań do BUTTON_TIME_BIT, BUTTON_ALARM_BIT
BUTTON_NEXT_BIT, BUTTON_ESC_BIT i zastanów się "co poetka miała na myśli"...
Natasza
Generalnie masz rację, ale w 8051 są obszary adresowane bitowo i ustawienie/wyzerowanie jednego bitu dokonywane jest za pomocą jednej instrukcji. Kompilatory dla 8051 posiadają pewne mechanizmy nie bedące standardem C właśnie do dostępu bitowego (umożliwiające zapis przykładowo: P0.0 = 1. Z drugiej strony każdy dobry kompilator powinien przetłumaczyć PORT |= 0b00000001 na SETB PORT.0 Powstaje więc dylemat, czy trzymać się standardu C czy kosztem nieprzenośności kodu korzystać z nietypowych ficzerów architektury.
AVR niestety nie do końca nadają się do wygodnego i przenośnego programowania w C (zwłaszcza w wydaniu avr-gcc). Kod który zaprezentowałeś (ten z _SFR_BYTE) można w zasadzie zastosować tylko pod avr-gcc. Ze względu na architekturę harwardzką dostęp do każdego typu pamięci musi być realizowany w inny sposób, co jest strasznie upierdliwe i utrudnia przenoszenie kodu z avr na inne uC i vice versa. A przykładowo w ST7 dostęp do każdego obszaru pamięci jest realizowany za pomocą tej samej instrukcji asm (co zarówno w C jak i w asm jest bardzo wygodne).
Pozatym makra sbi i cbi (które są funkcjonalną kopią instrukcji asemblera) wywodzą się jescze z czasów, gdy avr-gcc był w zasadzie makroasemblerem i już dawno powinny zostać zapomniane. Tego typu dziwolągi nie występują nigdzie indziej i pamiętanie o nich nic nie daje.
AVR niestety nie do końca nadają się do wygodnego i przenośnego programowania w C (zwłaszcza w wydaniu avr-gcc). Kod który zaprezentowałeś (ten z _SFR_BYTE) można w zasadzie zastosować tylko pod avr-gcc. Ze względu na architekturę harwardzką dostęp do każdego typu pamięci musi być realizowany w inny sposób, co jest strasznie upierdliwe i utrudnia przenoszenie kodu z avr na inne uC i vice versa. A przykładowo w ST7 dostęp do każdego obszaru pamięci jest realizowany za pomocą tej samej instrukcji asm (co zarówno w C jak i w asm jest bardzo wygodne).
Pozatym makra sbi i cbi (które są funkcjonalną kopią instrukcji asemblera) wywodzą się jescze z czasów, gdy avr-gcc był w zasadzie makroasemblerem i już dawno powinny zostać zapomniane. Tego typu dziwolągi nie występują nigdzie indziej i pamiętanie o nich nic nie daje.
Generalnie to wszytko zależy od implementacji języka C. Ja używam pakietu firmy Keil uVision dla uC rodziny 51. Pakiet ten jest dostępny też dla innych rodzin procesorów (80166, ARM) i już na pierwszy rzut oka widać, że każda z nich zawiera jakieś "ukłony" w stronę konkretnych architektur, które nijak się mają do znormalizowanego C.Najwidoczniej ktoś doszedł do wniosku, że warto korzystać z takich niestandardowych rozwiązań.
Moim zdaniem każdy niech pisze programy w sposób jaki mu odpowiada. Generalnie to z przenośnością jest różnie. Jak program trzeba będzie przenieść na innego procka, i np. użyć innego kompilatora to obok zmian zasadniczego kodu może się okazać konieczna zmiana dyrektyw preprocesora. One też są różne w zależności od tego co dany producent w tym temacie wykombinował.
Moim zdaniem każdy niech pisze programy w sposób jaki mu odpowiada. Generalnie to z przenośnością jest różnie. Jak program trzeba będzie przenieść na innego procka, i np. użyć innego kompilatora to obok zmian zasadniczego kodu może się okazać konieczna zmiana dyrektyw preprocesora. One też są różne w zależności od tego co dany producent w tym temacie wykombinował.