SlideShare una empresa de Scribd logo
1 de 27
UNGDUNGMAYTINH.COM
MỤC LỤC
Chương 11 I2C .................................................................................................................. 9
Bus I2C ........................................................................................................................... 9
Master và Slave .......................................................................................................... 9
Start và Stop.............................................................................................................. 10
Bit Dữ liệu................................................................................................................. 11
Địa chỉ I2C ................................................................................................................ 11
Giao tác I2C (I2C Transaction).............................................................................. 12
Chip mở rộng PCF8574 GPIO ............................................................................... 13
Mạch I2C ...................................................................................................................... 14
Đường PCF8574 INT .............................................................................................. 15
Cấu hình PCF8574 .................................................................................................... 16
Điều khiển GPIO của PCF8574............................................................................. 17
Tạo dạng sóng .......................................................................................................... 18
Mạch demo.................................................................................................................. 18
Ngắt EXTI.................................................................................................................. 19
Phần mềm I2C ........................................................................................................... 21
Kiểm tra I2C Sẵn sàng............................................................................................. 22
Bắt đầu I2C................................................................................................................ 22
Ghi I2C....................................................................................................................... 24
Đọc I2C ...................................................................................................................... 24
Khởi động lại I2C..................................................................................................... 25
Chương trình demo .................................................................................................. 25
Phiên Demo .............................................................................................................. 28
Tóm tắt ......................................................................................................................... 29
Chương 12 OLED ........................................................................................................... 31
Màn hình OLED .......................................................................................................... 31
Cấu hình.................................................................................................................... 32
Kết nối Màn hình..................................................................................................... 33
Tính năng hiển thị..................................................................................................... 34
Sơ đồ demo.................................................................................................................. 35
AFIO................................................................................................................................35
Đồ họa............................................................................................................................37
Pixmap ........................................................................................................................39
Ghi Pixmap................................................................................................................40
Phần mềm Vôn-kế....................................................................................................41
Mô-đun Main ............................................................................................................42
Demo ..............................................................................................................................44
Tóm tắt ..........................................................................................................................45
Chương 13 OLED Dùng DMA.......................................................................................47
Thách thức....................................................................................................................47
Mạch............................................................................................................................47
Hoạt động DMA...........................................................................................................47
Thực thi DMA...........................................................................................................48
Demo ..............................................................................................................................52
Khởi tạo DMA...........................................................................................................53
Khởi động DMA.......................................................................................................54
Tác vụ Quản lý SPI/DMA OLED...........................................................................54
Chương trình DMA ISR..........................................................................................57
Khởi động lại chuyển DMA...................................................................................58
Thực thi Demo.............................................................................................................59
Những thách thức khác ...........................................................................................60
Tóm tắt ..........................................................................................................................61
Chương 14 Analog-to-Digital Conversion ................................................................63
Nguồn STM32F103C8T6..........................................................................................63
Demo ..............................................................................................................................64
Đầu vào Analog PA0 và PA1..................................................................................64
Cấu hình ngoại vi ADC...........................................................................................64
Chạy Demo ...................................................................................................................67
Đọc ADC ....................................................................................................................68
Điện áp Analog............................................................................................................70
Tóm tắt ..........................................................................................................................72
UNGDUNGMAYTINH.COM
Chương 15 Hệ thống Xung.......................................................................................... 73
Mở đầu .......................................................................................................................... 73
Mạch Dao động RC ................................................................................................. 74
Dao động Thạch anh............................................................................................... 75
Công suất Dao động................................................................................................ 75
Xung Thời gian thực................................................................................................. 76
Xung Watchdog ......................................................................................................... 76
Xung Hệ thống (SYSCLK)....................................................................................... 76
SYSCLK và USB....................................................................................................... 79
Bus AHB........................................................................................................................ 80
rcc_clock_setup_in_hse_8mhz_out_72mhz()...................................................... 81
Thiết bị Ngoại vi APB1........................................................................................... 84
Thiết bị Ngoại vi APB2........................................................................................... 84
Timer (bộ định thời)................................................................................................ 84
rcc_set_mco()............................................................................................................ 84
Bản demo HSI ............................................................................................................ 85
Bản demo HSE............................................................................................................ 86
Bản demo PLL ÷ 2..................................................................................................... 87
Tóm tắt ......................................................................................................................... 88
Chương 16 PWM với Timer 2 ...................................................................................... 89
Tín hiệu PWM.............................................................................................................. 89
Timer 2.......................................................................................................................... 90
Vòng lặp PWM............................................................................................................ 93
Tính toán Prescale Timer ....................................................................................... 93
Tần số 30 Hz.............................................................................................................. 94
Đấu nối Servo............................................................................................................. 95
Chạy Demo .................................................................................................................. 96
PWM trên PB3 ............................................................................................................ 96
Các Timer Khác .......................................................................................................... 97
Kênh PWM khác...................................................................................................... 98
Tóm tắt ......................................................................................................................... 98
Chương 17 Input PWM với Timer 4 ............................................................................99
Tín hiệu Servo .............................................................................................................99
Điện áp tín hiệu ........................................................................................................100
Dự án Demo...............................................................................................................100
Cấu hình GPIO .......................................................................................................100
Cấu hình Timer 4....................................................................................................100
Vòng lặp Task1 .......................................................................................................102
Chương trình ISR ...................................................................................................102
Chạy Demo .................................................................................................................103
Đầu ra Phiên (Session Output)............................................................................105
Đầu vào Timer...........................................................................................................106
Tóm tắt ........................................................................................................................107
Chương 18 Bus CAN....................................................................................................109
CAN Bus.......................................................................................................................109
Tín hiệu vi sai ............................................................................................................111
Trội/lặn .....................................................................................................................112
Phân xử Bus...............................................................................................................113
Đồng bộ hóa ............................................................................................................114
Định dạng Tin nhắn...............................................................................................114
Giới hạn STM32.........................................................................................................116
Demo ............................................................................................................................116
Build Phần mềm .....................................................................................................116
Giao diện UART.....................................................................................................117
Nạp flash cho MCU................................................................................................117
Demo Bus.................................................................................................................118
Phiên Chạy..................................................................................................................119
Tin nhắn CAN.........................................................................................................121
Đồng bộ....................................................................................................................121
Tóm tắt ........................................................................................................................121
Chương 19 Phần mềm Bus CAN...............................................................................123
Khởi tạo .......................................................................................................................123
UNGDUNGMAYTINH.COM
can_init().................................................................................................................. 125
Các bộ lọc Nhận CAN........................................................................................... 126
Các ngắt Nhận CAN.............................................................................................. 127
Nhận Ứng dụng ..................................................................................................... 130
Gửi Tin nhắn CAN................................................................................................ 132
Tóm tắt ....................................................................................................................... 133
Chương 20 Dự án Mới................................................................................................. 135
Tạo Dự án................................................................................................................... 135
Makefile .................................................................................................................. 136
Bao gồm Makefiles................................................................................................ 138
Header Phụ thuộc .................................................................................................. 138
Tùy chọn biên dịch................................................................................................ 138
Nạp flash 128k........................................................................................................ 139
FreeRTOS ................................................................................................................... 139
rtos/opencm3.c........................................................................................................ 139
rtos/heap_4.c ........................................................................................................... 140
Mô-đun bắt buộc.................................................................................................... 141
FreeRTOSConfig.h................................................................................................... 141
Thư viện Người dùng............................................................................................. 143
Lỗi Rookie.................................................................................................................. 144
Tóm tắt ....................................................................................................................... 144
Chương 21 Xử lý Sự cố.............................................................................................. 145
Gnu GDB..................................................................................................................... 145
Máy chủ GDB......................................................................................................... 145
GDB từ xa................................................................................................................ 146
Giao diện Người dùng Văn bản GDB............................................................... 149
Sự cố Ngoại vi GPIO............................................................................................... 150
Chức năng Thay thế thất bại .............................................................................. 151
Lỗi ngoại vi ................................................................................................................ 151
ISR FreeRTOS Crash .............................................................................................. 152
Stack Overflow......................................................................................................... 152
Ước tính Kích thước Stack....................................................................................153
Khi một Debugger không trợ giúp.....................................................................153
Push/Pull hoặc Cực máng Mở.............................................................................154
Lỗi Ngoại vi ................................................................................................................154
Tài liệu .........................................................................................................................154
libopencm3 ..............................................................................................................155
Các ưu tiên của Tác vụ FreeRTOS......................................................................156
Tạo lịch trình trong libopencm3..........................................................................157
Tóm tắt ........................................................................................................................158
UNGDUNGMAYTINH.COM
Chương 11
I2C
Bus I2C là một hệ thống phần cứng tiện lợi bởi vì nó chỉ sử dụng hai dây để giao
tiếp. Bus cũng được biết đến với các tên khác, chẳng hạn như IIC (inter-integrated
circuit: liên mạch tích hợp) hoặc TWI (two-wire interface: giao diện hai dây). Phillips
Semiconductor đã phát triển bus I2C, sau đó Intel mở rộng với giao thức SMBus.
Đây là các giao thức tương tự nhau, nhưng tôi sẽ tập trung vào I2C trong chương
này.
Với tiện ích của bus I2C, không có gì ngạc nhiên khi nền tảng STM32 bao gồm phần
cứng ngoại vi cho nó. Chương này sẽ khám phá cách sử dụng thiết bị ngoại vi kết
nối với thiết bị mở rộng GPIO PCF8574 được gắn vào bus.
Bus I2C
Một trong những điểm nổi bật của một bus truyền thông nối tiếp I2C là nó chỉ sử
dụng hai dây. Nguồn cung cấp và kết nối với đất không được bao gồm trong phần
này. Hai đường truyền liên quan như sau:
• Xung hệ thống (System Clock, thường được gắn nhãn SCL)
• Dữ liệu hệ thống (System Data, thường được gắn nhãn SDA)
Mỗi dây này nằm ở mức điện áp cao (thường là 5 hoặc 3,3V). Bất kỳ thiết bị nào trên
bus đều có thể tạo ra tín hiệu dữ liệu bằng cách kéo dây xuống mức low (0 V). Điều
này hoạt động tốt cho các transistor cực góp mở (lưỡng cực) hoặc cực máng mở
(FET). Khi transistor hoạt động, chúng hoạt động giống như một công tắc làm ngắn
dòng bus xuống đất. Khi bus không được kết nối, một điện trở kéo lên làm điện áp
của đường dây ở mức high. Vì lý do này, cả hai dây I2C hoạt động với ít nhất một
điện trở kéo lên.
Master và Slave
Với mỗi thiết bị trên bus có thể kéo các dây xuống mức low, phải có một số loại giao
thức để giữ mọi thứ được ngăn nắp. Nếu không, trên bus sẽ có nhiều mẩu tin giao
tiếp truyền đi mà không có đầu nhận nào biết được gì. Vì lý do này, giao thức I2C
thường sử dụng một thiết bị Master và nhiều thiết bị Slave. Trong các hệ thống phức
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 9
tạp hơn, có thể có nhiều hơn một bộ điều khiển Master, nằm ngoài phạm vi của
chương này.
Thiết bị Master luôn bắt đầu giao tiếp và điều khiển tín hiệu xung. Ngoại lệ cho dây
SCL đang được điều khiển bởi những phần Slave đôi khi có thể kéo dài xung để cấp
thêm thời gian (khi nó được Master hỗ trợ). Xung kéo dài xảy ra khi thiết bị Slave
tiếp tục giữ dây SCL ở mức low sau khi Master đã giải phóng nó.
Các thiết bị Slave chỉ phản hồi khi được nói đến. Mỗi slave có một địa chỉ thiết bị 7-
bit duy nhất để nó biết khi một tin nhắn bus đã được gửi đến nó. Đây là một khía
cạnh mà I2C khác với bus SPI. Mỗi thiết bị I2C được gắn địa chỉ bởi một byte địa
chỉ, trong khi các thiết bị SPI được chọn bởi một dây chọn chip.
Start và Stop
I2C không hoạt động khi cả hai đường SDA và SCL đều ở mức high. Trong trường
hợp này, không có thiết bị - Master hoặc Slave - làm các bus ở mức low.
Sự bắt đầu của một giao tác I2C được chỉ định bởi các event sau:
1. Dây SCL vẫn ở mức high.
2. Dây SDA bị kéo xuống mức low.
Bước hai thường xảy ra trong một chu kỳ xung, mặc dù nó không cần phải chính
xác như vậy. Khi bus không hoạt động, đủ để thấy dây SDA xuống mức thấp trong
khi SCL vẫn ở mức high. Hình 11-1 minh họa tín hiệu I2C bắt đầu, dừng và lặp lại.
Hình 11-1. I2C bắt đầu, dừng và lặp lại tín hiệu bit bắt đầu
Chế độ repeated start vừa tối ưu hóa stop và start, vừa là một cách để giữ bus trong
khi tiếp tục một giao tác I2C dài hơn. Chúng ta sẽ thảo luận thêm về điều này sau.
TRUNG TÂM ADVANCECAD
10 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
Bit Dữ liệu
Các bit dữ liệu được truyền đi cùng với tín hiệu chuyển tiếp từ cao đến thấp trong
tín hiệu xung (SCL). Hình 11-2 minh họa.
Hình 11-2. Tín hiệu bit dữ liệu I2C
Việc lấy mẫu bus SDA xảy ra khi các mũi tên được hiển thị. Mức high hoặc low của
dây SDA được đọc tại thời điểm mà dây SCL được kéo xuống mức low (bởi Master).
Địa chỉ I2C
Trước khi chúng ta xem xét toàn bộ giao tác bus, hãy mô tả byte địa chỉ, được sử
dụng để xác định thiết bị slave sẽ đáp ứng (Hình 11-3). Ngoài các bit địa chỉ, bit
đọc/ghi cho biết ý định đọc hoặc ghi từ/đến thiết bị Slave.
Hình 11-3. Định dạng địa chỉ 7-bit I2C
7 bit địa chỉ được dịch chuyển lên 1 bit trong byte địa chỉ, trong khi bit đọc/ghi ở
bên phải. Bit đọc/ghi được định nghĩa như sau:
• bit-1 cho biết thao tác đọc từ thiết bị Slave sẽ sử dụng
• bit-0 cho biết thao tác ghi vào thiết bị Slave sẽ sử dụng
Địa chỉ và bit đọc/ghi luôn theo một bit bắt đầu hoặc lặp lại bắt đầu trên bus I2C. Bit
bắt đầu yêu cầu bộ điều khiển I2C để kiểm tra rằng bus không được sử dụng bởi
một Master khác; nó thực hiện điều này bằng cách sử dụng một thủ tục xem xét bus
(khi đa-Master được hỗ trợ). Nhưng khi truy cập bus thành công, bus được sở hữu
bởi bộ điều khiển cho đến khi nó được xuất với một bit dừng.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 11
Việc bắt đầu lặp lại cho phép giao thức hiện tại tiếp tục mà không cần xem xét bus.
Vì một địa chỉ và bit đọc/ghi phải tuân thủ, điều này cho phép nhiều Slave được hỗ
trợ với một giao tác. Ngoài ra, cùng một Slave có thể được giải quyết nhưng được
truy cập với một chế độ đọc/ghi khác.
Mẹo Đôi khi mọi người báo cáo rằng các địa chỉ Slave được dịch chuyển lên một
bit khi chúng được gửi đi. Điều này có tác dụng nhân địa chỉ cho hai. Địa chỉ 0x42
khi chuyển sang phải trở thành 0x21. Xem điều này trong tài liệu.
Giao tác I2C (I2C Transaction)
Hình 11-4 minh họa một giao tác ghi và đọc (không sử dụng bắt đầu lặp lại).
Hình 11-4. Giao tác ghi và giao tác đọc I2C
Phần trên của Hình 11-4 minh họa một giao tác ghi đơn giản. Chuỗi cơ bản của event
để viết minh họa như sau:
1. Bộ điều khiển I2C điều khiển bus và phát ra bit khởi động.
2. Bộ điều khiển (Master) ghi ra 7 bit địa chỉ theo sau là một bit-0, chỉ ra rằng
đây sẽ là một giao tác ghi.
3. Thiết bị Slave báo nhận yêu cầu và kéo dây data xuống mức low trong bit
ACK (acknowledge: báo nhận). Nếu không có Slave đáp ứng, dây data sẽ ở
mức high và tạo ra một NAK (negative acknowledge: báo nhận âm) để được
nhận bởi bộ điều khiển.
4. Bởi vì đây là một giao tác ghi, byte dữ liệu được ghi ra.
TRUNG TÂM ADVANCECAD
12 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
5. Thiết bị slave báo nhận việc nhận byte dữ liệu bằng cách kéo dây data xuống
mức low trong thời gian bit ACK.
6. Master không gửi thêm dữ liệu, nên nó ghi một bit dừng và giải phóng bus
I2C.
Yêu cầu đọc cũng tương tự:
1. Bộ điều khiển I2C điều khiển bus và phát ra bit khởi động.
2. Bộ điều khiển (Master) ghi ra bảy bit địa chỉ theo sau là bit-1, cho biết đây sẽ
là một giao tác đọc.
3. Thiết bị Slave báo nhận yêu cầu và kéo dây data xuống mức low trong bit
ACK. Nếu không có Slave đáp ứng, dây data sẽ ở mức high và NAK sẽ được
bộ điều khiển nhận.
4. Bởi vì đây là một giao tác đọc, Master tiếp tục ghi ra các bit xung để cho phép
thiết bị Slave đồng bộ hóa dữ liệu của nó để phản hồi cho Master.
5. Với mỗi xung clock, thiết bị Slave ghi ra tám byte dữ liệu vào bộ điều khiển
Master.
6. Trong thời gian ACK, bộ điều khiển Master thường gửi NAK khi không có
thêm byte nào được đọc.
7. Bộ điều khiển gửi bit dừng, luôn luôn kết thúc giao thức với Slave (bất kể
ACK/NAK cuối cùng đã gửi).
Chip mở rộng PCF8574 GPIO
Để thực hành bus I2C trong chương này, chúng ta sẽ sử dụng chip mở rộng PCF8574
GPIO (Hình 11-5). Đây là một chip tuyệt vời để thêm các dây GPIO bổ sung, miễn
là bạn không cần tốc độ cao (bản demo vận hành bus I2C ở 100 kHz).
Hình 11-5. Sơ đồ chân của PCF8574P
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 13
Điện áp +3.3V được áp dụng cho chân 16, trong khi kết nối nối đất là chân 8. Chân
A0 đến A2 được sử dụng để chọn địa chỉ Slave của chip (Bảng 11-1). Chân P0 đến
P7 là các chân dữ liệu GPIO, có thể là đầu vào hoặc đầu ra. Chân 14 kết nối với xung
(SCL), trong khi chân 15 kết nối với đường data (SDA). Chân 13 có thể được sử dụng
để thông báo.
Bảng 11-1. Cấu hình Địa chỉ PCF8574
A0 A1 A2 Địa chỉ PCF8574 Địa chỉ PCF8574A
0 0 0 0x20 0x38
0 0 1 0x21 0x39
0 1 0 0x22 0x3A
0 1 1 0x23 0x3B
1 0 0 0x24 0x3C
1 0 1 0x25 0x3D
1 1 0 0x26 0x3E
1 1 1 0x27 0x3F
Các dòng địa chỉ A0 đến A2 được lập trình thành 0 khi được nối đất và thành các
bit-1 khi được kết nối với Vcc (+3.3V trong bản demo này). Nếu bạn có chip
PCF8575A, thì địa chỉ sẽ được lấy từ cột bên phải. Chip PCF8574 trước đó sử dụng
địa chỉ thập lục phân ở cột bên trái của bảng.
Mạch I2C
Hình 11-6 minh họa ba thiết bị PCF8574P gắn vào STM32 thông qua bus I2C.
TRUNG TÂM ADVANCECAD
14 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
Hình 11-6. STM32 nối với ba thiết bị Slave PCF8574P sử dụng bus I2C
Sơ đồ hơi nhiều dây nối, nhưng nó dễ hình dung. Lưu ý rằng bus I2C chỉ bao gồm
một cặp dây, SCL và SDA, xuất phát từ STM32. Hai dây này được kéo lên mức high
bởi các điện trở R1 và R2. Mỗi thiết bị Slave cũng được kết nối với các đường bus
này, cho phép mỗi thiết bị này phản hồi khi nó nhận ra địa chỉ Slave của nó.
Chú ý rằng IC1, IC2 và IC3 có hệ thống nối dây khác nhau cho các chân địa chỉ A0,
A1 và A2. Điều này cấu hình mỗi thiết bị để đáp ứng với một địa chỉ Slave khác
nhau (xem Bảng 11-1). Các địa chỉ này phải là duy nhất.
Đường PCF8574 INT
Các kết nối còn lại trong Hình 11-6 là nguồn và đường INT . Đường INT là một
thành phần bus tùy chọn không liên quan gì đến bus I2C. Bạn có thể không cần gắn
tất cả các thiết bị PCF8574P vào đường INT nếu chúng không được sử dụng cho
đầu vào GPIO.
Đường INT cho biết rằng GPIO đầu vào đã thay đổi và được gắn vào đường ngắt
vi xử lý. Điều này giúp tiết kiệm MCU từ việc liên tục sử dụng các thiết bị I2C để
xem liệu một nút đã được nhấn chưa. Nếu bất kỳ đầu vào nào thay đổi từ mức cao
xuống thấp hoặc thấp đến cao, thì transistor trong PCF8574 được kích hoạt và kéo
đường INT xuống mức low. Nó sẽ ở mức low cho đến khi thiết bị có “dịch vụ” ngắt.
Một thao tác đọc hoặc ghi đơn giản tới thiết bị ngoại vi là tất cả những gì cần thiết
để phục vụ ngắt.
Dây INT không xác định thiết bị Slave nào đã đăng ký thay đổi. MCU vẫn phải
kiểm tra các thiết bị Slave tham gia để xem sự thay đổi xảy ra ở đâu.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 15
Điều quan trọng cần lưu ý là có một giới hạn nhỏ. Nếu thay đổi mức GPIO xảy ra
quá nhanh, sẽ không có ngắt nào được tạo ra. Cũng có thể xảy ra event thay đổi
GPIO trong chu kỳ ACK/NAK khi ngắt được xóa. Một ngắt xảy ra sau đó cũng có
thể bị mất. Datasheet của NXP (hãng NXP Semiconductors) chỉ ra rằng phải mất 4
μs từ một thay đổi GPIO được nhận biết đến lúc kích hoạt dây INT . Thời gian còn
lại sẽ bao gồm đáp ứng ngắt và xử lý phần mềm của MCU.
Cấu hình PCF8574
Datasheet từ hãng NXP Semiconductors mô tả các cổng I/O như quasi-bidirectional
(gần như hai chiều). Điều này có nghĩa là các cổng GPIO (P0 đến P7) có thể được sử
dụng làm output hoặc được đọc trực tiếp như input, mà không cần bất kỳ cấu hình
nào thông qua thanh ghi thiết bị.
Để gửi một giá trị đầu ra, bạn chỉ cần ghi vào thiết bị PCF8574 qua bus I2C. Mặt
khác, đầu vào GPIO yêu cầu một mẹo nhỏ - nơi bạn cần đầu vào GPIO, trước hết
bạn ghi bit-1 vào cổng GPIO. Để xem cách thức hoạt động, xem lại Hình 11-7.
Hình 11-7. Mạch GPIO đơn giản PCF8574
Bắt đầu ở phía trên cùng của sơ đồ nơi đặt Vcc (+3.3 V). Bên trong chip là một nguồn-
dòng 100 μA nối tiếp với các transistor M2 và M1. Do đó, khi một bit cao (bit-1) được
ghi vào cổng GPIO, transistor M2 được bật và M1 bị tắt (được điều khiển bởi “điều
khiển hi/lo” bên trong chip). Transistor M3 đang tắt tại thời điểm này.
Nếu bạn nối GPIO xuống đất, nguồn-dòng giới hạn dòng điện đến 100 μA khi nó
đi qua M2 và ra khỏi chân GPIO xuống đất (mũi tên phải trong Hình 11-7). Trong
khi đó, bên trong của PCF8574 có thể nhận ra mức low trên “Read Input” bên trong
TRUNG TÂM ADVANCECAD
16 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
được nối với GPIO, được đọc ngược lại như là một bit-0. Bằng cách ghi bit-1 cho
GPIO, bạn cho phép một mạch bên ngoài kéo áp xuống mức low, hoặc để nó ở mức
high. Dòng điện luôn giới hạn ở mức 100 μA, vì vậy không có tác hại gì xảy ra.
Nếu, thay vào đó, chân GPIO được ghi là bit-0, transistor M1 sẽ luôn được bật, làm
đoản mạch GPIO. Kết quả là “Read Input” sẽ luôn luôn nhận bit-0. Theo quy tắc
đơn giản là viết bit-1 cho GPIO, bạn có thể nhận ra được khi nào nó được nối xuống
đất làm đầu vào.
Điều khiển GPIO của PCF8574
Thiết kế gần như hai chiều của GPIO có một hệ quả. Bạn đã thấy rằng đầu ra GPIO
bị đoản mạch được hạn dòng ở 100 μA. Điều này có nghĩa là GPIO không thể hoạt
động như một nguồn cấp dòng cho một LED. Một LED điển hình cần dòng điện
khoảng 10mA, gấp 100 lần so với GPIO này có khả năng cung cấp!
Hình 11-8. Điều khiển tải dòng cao hơn với PCF8574
Tuy nhiên, transistor M1 có thể xử lý tối đa 25 mA nếu bạn sử dụng chân GPIO để
xả nguồn cho LED. Hình 11-8 minh họa cách điều khiển một LED.
LED và điện trở R1 được cấp nguồn từ Vcc, với dòng không bị giới hạn. Vì vậy, M1
hoạt động như một công tắc để xả dòng điện xuống đất, bật sáng LED. Tác động
nguồn của điều này là bạn cần phải viết một bit-0 để bật LED.
Lưu ý Dù chế độ điều khiển ở mức cao của PCF8574 bị giới hạn ở 100 μA, điều này
là đủ để điều khiển các đầu vào tín hiệu CMOS khác.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 17
Tạo dạng sóng
Khi đầu ra GPIO được viết dưới dạng bit-1, chỉ có dòng điện 100 μA có sẵn để kéo
nó lên tới Vcc. Điều này trình bày một vấn đề nhỏ khi nó hiện đang ở điện thế thấp,
dẫn đến một thời gian tăng chậm.
Các nhà thiết kế của PCF8574 bao gồm một mạch với transistor M3 thường tắt (Hình
11-8). Tuy nhiên, khi thiết bị được ghi vào, mỗi GPIO nhận một bit-1 được tăng từ
M3 trong chu kỳ I2C ACK/NAK. Điều này giúp cung cấp sự chuyển đổi từ thấp đến
cao một cách nhanh chóng trên các đầu ra. Khi chu kỳ ACK/NAK hoàn tất, M3 sẽ
tắt một lần nữa, để lại giới hạn dòng điện 100 μA để duy trì đầu ra ở mức cao.
Mạch demo
Hình 11-9 minh họa mạch cuối cùng cho chương trình demo. Những thay đổi đáng
chú ý là chỉ có một chip PCF8574 được sử dụng, cùng với hai LED và một nút nhấn.
Hình 11-9. I2C demo với LED và nút nhấn
Khi nối dây mạch này, đừng quên nối điện trở kéo lên R3 sao cho điện thế không sử
dụng của GPIO PC14 cao. Cũng lưu ý rằng cả hai LED đều được cung cấp từ dòng
Vcc sao cho các cổng P0 và P1 xả dòng điện để bật sáng các LED. Cổng P7 sẽ đọc
nút ấn, thường nó sẽ ở mức cao (nhớ lại rằng cổng được cấp ở mức cao bởi nguồn-
TRUNG TÂM ADVANCECAD
18 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
dòng 100 μA trong PCF8574). Khi nhấn nút, P7 sẽ được nối với đất, làm cho đầu ra
đọc bit-0.
Ngắt EXTI
Dự án RTC2 sử dụng ngắt EXTI để đạt được một ngắt báo động riêng biệt. Một vài
bước nữa là cần thiết để đạt được ngắt trên PC14 cho ngắt/INT. Hãy xem phần mềm
liên quan. Phần mềm dự án cho chương này được tìm thấy trong danh mục:
$ cd ~/stm32f103c8t6/rtos/i2c-pcf8574
Ban đầu, chúng ta sẽ kiểm tra thiết lập I2C và EXTI trong chương trình main() của
main.c (Bản kê 11-1).
Bản kê 11-1. Thiết lập Ban đầu của các Ngắt I2C Ngoại vi và EXTI
0197: int
0198: main(void) {
0199:
0200: rcc_clock_setup_in_hse_8mhz_out_72mhz();// For "blue pill"
0201: rcc_periph_clock_enable(RCC_GPIOB); // I2C
0202: rcc_periph_clock_enable(RCC_GPIOC); // LED
0203: rcc_periph_clock_enable(RCC_AFIO); // EXTI
0204: rcc_periph_clock_enable(RCC_I2C1); // I2C
0205:
0206: gpio_set_mode(GPIOB,
0207: GPIO_MODE_OUTPUT_50_MHZ,
0208: GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
0209: GPIO6|GPIO7); // I2C
0210: gpio_set(GPIOB,GPIO6|GPIO7); // Idle high
0211:
0212: gpio_set_mode(GPIOC,
0213: GPIO_MODE_OUTPUT_2_MHZ,
0214: GPIO_CNF_OUTPUT_PUSHPULL,
0215: GPIO13); // LED on PC13
0216: gpio_set(GPIOC,GPIO13); // PC13 LED dark
0217:
0218: // AFIO_MAPR_I2C1_REMAP=0, PB6+PB7
0219: gpio_primary_remap(0,0);
0220:
0221: gpio_set_mode(GPIOC, // PCF8574 /INT
0222: GPIO_MODE_INPUT, // Input
0223: GPIO_CNF_INPUT_FLOAT,
0224: GPIO14); // on PC14
0225:
0226: exti_select_source(EXTI14,GPIOC);
0227: exti_set_trigger(EXTI14,EXTI_TRIGGER_FALLING);
0228: exti_enable_request(EXTI14);
0229: nvic_enable_irq(NVIC_EXTI15_10_IRQ); // PC14 <- /INT
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 19
Các dòng từ 201 đến 204 cho phép các xung của GPIOB (cho I2C), GPIOC (cho INT
đọc LED và PC14), EXTI và thiết bị ngoại vi I2C. Dòng 206 cấu hình GPIO PB6 và
PB7 cho hoạt động mở cống cho thiết bị ngoại vi I2C. Dòng 210 có thể không hoàn
toàn cần thiết, nhưng cho đến khi thiết bị ngoại vi I2C được cấu hình, các đường
bus I2C nên được đặt ở mức cao.
Dòng 219 cấu hình I2C1 để sử dụng PB6 và PB7. Hàm libopencm3
gpio_primary_remap() có thể được sử dụng để thực hiện các lựa chọn khác. PB6 và
PB7 hữu ích hơn vì chúng có nguồn đầu vào 5 V.
Dòng 221 thiết lập GPIO PC14 làm đầu vào ở chế độ nổi. Đường này sẽ được R3 nối
ở mức cao trong Hình 11-9.
Dòng 226 đến 229 cấu hình ngắt EXTI. Hàm exti_select_source() chọn GPIO PC14
để thêm vào danh sách các nguồn ngắt. Dòng 227 sau đó cấu hình rằng ngắt sẽ xảy
ra khi tín hiệu giảm từ cao xuống thấp. Cuối cùng, dòng 228 cho phép thiết bị ngoại
vi EXTI yêu cầu ngắt. Các hàm gọi đến nvic_enable_irq() cho phép các vector ngắt
NVIC_EXTI15_10_IRQ. Khi ngắt này xảy ra, đầu vào exti15_10_isr() sẽ được gọi.
Để giúp bạn đỡ đau đầu phải tra cứu datasheet (RM0008) từ hãng ST
Microelectronics, Bảng 11-2 được cung cấp. Theo ý kiến của tôi, datasheet không rõ
ràng về cách ngắt cho EXTI được hỗ trợ. Bảng này cho thấy các dòng từ 0 đến 4 có
vectơ ngắt riêng của chúng. Nhưng đối với các cổng GPIO đánh số từ 5 đến 9 hoặc
từ 10 đến 15, các vectơ ngắt được chia sẻ rộng rãi hơn.
Bảng 11-2. Danh sách Ngắt EXTI STM32F103 và Tên Chương trình ISR
Ngắt Chương trình ISR Mô tả
NVIC_EXTI0_IRQ exti0_isr() Dòng 0: PA0/PB0/PC0
NVIC_EXTI1_IRQ exti1_isr() Dòng 1: PA1/PB1/PC1
NVIC_EXTI2_IRQ exti2_isr() Dòng 2: PA2/PB2/PC2
NVIC_EXTI3_IRQ exti3_isr() Dòng 3: PA3/PB3/PC3
NVIC_EXTI4_IRQ exti4_isr() Dòng 4: PA4/PB4/PC4
NVIC_EXTI9_5_IRQ exti9_5_isr() Dòng 5 đến 9: PA5-9/PB5-9/PC5-9
NVIC_EXTI15_10_IRQ exti15_10_isr() Dòng 10 đến 15: PA10-15/PB10-15/PC10-15
NVIC_PVD_IRQ pvd_isr() Dòng 16: Power
TRUNG TÂM ADVANCECAD
20 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
Ngắt Chương trình ISR Mô tả
NVIC_RTC_ALARM_IRQ rtc_alarm_isr() Dòng 17: RTC Alarm
NVIC_USB_WAKEUP_IRQ usb_wakeup_isr() Dòng 18: USB Wakeup
Phần mềm I2C
Mã nguồn để điều khiển thiết bị ngoại vi I2C đã được đặt trong mô đun nguồn i2c.c.
Hàm quan tâm đầu tiên là i2c_configure(), được minh họa trong Bản kê 11-2.
Bản kê 11-2. Cấu hình I2C
0061: void
0062: i2c_configure(I2C_Control *dev,uint32_t i2c,uint32_t ticks) {
0063:
0064: dev->device = i2c;
0065: dev->timeout = ticks;
0066:
0067: i2c_peripheral_disable(dev->device);
0068: i2c_reset(dev->device);
0069: I2C_CR1(dev->device) &= ~I2C_CR1_STOP; // Clear stop
0070: i2c_set_standard_mode(dev->device); // 100 kHz mode
0071: i2c_set_clock_frequency(dev->device,I2C_CR2_FREQ_36MHZ); // APB
Freq
0072: i2c_set_trise(dev->device,36); // 1000 ns
0073: i2c_set_dutycycle(dev->device,I2C_CCR_DUTY_DIV2);
0074: i2c_set_ccr(dev->device,180); // 100 kHz <= 180 * 1
/36M
0075: i2c_set_own_7bit_slave_address(dev->device,0x23);
0076: i2c_peripheral_enable(dev->device);
0077: }
Cấu trúc có tên I2C_Control được truyền vào làm đối số đầu tiên để giữ cấu hình.
Địa chỉ ngoại vi I2C được truyền trong đối số i2c, sẽ là I2C1 cho bản demo này. Đối
số cuối cùng xác định thời gian chờ được sử dụng, tính theo nhịp (tick). Các giá trị
này được giữ nguyên trong I2C_Control trong các dòng 64 và 65 để sử dụng sau
này.
Các dòng 67 đến 69 xóa và reset thiết bị ngoại vi I2C để nếu nó bị lỗi, nó có thể
“không làm cản trở”. Một trong những nhược điểm của I2C là giao thức đôi khi có
thể treo nếu có lỗi xảy ra trên bus.
Các dòng 70 đến 76 cấu hình thiết bị ngoại vi I2C và kích hoạt nó. Dòng 75 chỉ cần
thiết nếu bạn muốn vận hành bộ điều khiển ở chế độ Slave.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 21
Kiểm tra I2C Sẵn sàng
Trước khi bất kỳ hoạt động I2C nào có thể được khởi tạo, bạn phải kiểm tra xem
thiết bị có đang được sử dụng không. Nếu không, yêu cầu của bạn có thể bị bỏ qua
hoặc sẽ gây lỗi cho hoạt động hiện tại. Bản kê 11-3 cho thấy chương trình được sử
dụng.
Bản kê 11-3. Kiểm tra I2C Sẵn sàng
0083: void
0084: i2c_wait_busy(I2C_Control *dev) {
0085:
0086: while ( I2C_SR2(dev->device) & I2C_SR2_BUSY )
0087: taskYIELD(); // I2C Busy
0088:
0089: }
Chương trình này sử dụng chương trình libopencm3 và macro để quản lý các thiết
bị ngoại vi. Tuy nhiên, nếu thiết bị đang được sử dụng, điều khiển được chuyển đến
các tác vụ FreeRTOS khác bằng cách sử dụng câu lệnh taskYIELD().
Bắt đầu I2C
Để bắt đầu một giao tác bus I2C, thiết bị ngoại vi phải thực hiện thao tác “khởi
động”. Điều này có thể liên quan đến xử lý bus nếu có nhiều Master đang được sử
dụng. Bản kê 11-4 cho thấy chương trình được sử dụng trong bản demo.
Bản kê 11-4. Hàm khởi động I2C
0095: void
0096: i2c_start_addr(I2C_Control *dev,uint8_t addr,enum I2C_RW rw) {
0097: TickType_t t0 = systicks();
0098:
0099: i2c_wait_busy(dev); // Block until not busy
0100: I2C_SR1(dev->device) &= ~I2C_SR1_AF; // Clear Acknowledge failure
0101: i2c_clear_stop(dev->device); // Do not generate a Stop
0102: if ( rw == Read )
0103: i2c_enable_ack(dev->device);
0104: i2c_send_start(dev->device); // Generate a Start/Restart
0105:
0106: // Loop until ready:
0107: while ( !((I2C_SR1(dev->device) & I2C_SR1_SB)
0108: && (I2C_SR2(dev->device) & (I2C_SR2_MSL|I2C_SR2_BUSY))) ) {
0109: if ( diff_ticks(t0,systicks()) > dev->timeout )
0110: longjmp(i2c_exception,I2C_Addr_Timeout);
0111: taskYIELD();
0112: }
0113:
0114: // Send Address & R/W flag:
TRUNG TÂM ADVANCECAD
22 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
0115: i2c_send_7bit_address(dev->device,addr,
0116: rw == Read ? I2C_READ : I2C_WRITE);
0117:
0118: // Wait until completion, NAK, or timeout
0119: t0 = systicks();
0120: while ( !(I2C_SR1(dev->device) & I2C_SR1_ADDR) ) {
0121: if ( I2C_SR1(dev->device) & I2C_SR1_AF ) {
0122: i2c_send_stop(dev->device);
0123: (void)I2C_SR1(dev->device);
0124: (void)I2C_SR2(dev->device); // Clear flags
0125: // NAK Received (no ADDR flag will be set here)
0126: longjmp(i2c_exception,I2C_Addr_NAK);
0127: }
0128: if ( diff_ticks(t0,systicks()) > dev->timeout )
0129: longjmp(i2c_exception,I2C_Addr_Timeout);
0130: taskYIELD();
0131: }
0132:
0133: (void)I2C_SR2(dev->device); // Clear flags
0134: }
Bước đầu tiên là để xác định nhịp thời gian (tick time) hiện tại trong dòng 97. Điều
này cho phép chúng ta định thời cho thao tác và thời gian hết nếu cần thiết. Dòng
99 đợi cho thiết bị ngoại vi sẵn sàng. Khi đã sẵn sàng, dòng 100 xóa lỗi báo nhận,
nếu có. Dòng 101 chỉ ra rằng không có điểm dừng nào được tạo ra.
Nếu hoạt động là đọc, hàm i2c_enable_ack() được gọi để cho phép nhận ACK từ
Slave. Thiết bị ngoại vi sau đó được yêu cầu tạo bit bắt đầu trong dòng 104.
Các dòng 107 và 108 kiểm tra nếu bit bắt đầu đã được tạo ra. Nếu nó chưa được tạo
ra, dòng 109 và 110 kiểm tra và thực hiện một longjmp() nếu hoạt động đã hết thời
gian chờ. Chúng ta sẽ nói thêm về longjmp() hoạt động như một ngoại lệ sau này.
Nếu không được hẹn giờ, câu lệnh FreeRTOS taskYIELD() được thực hiện để chia
sẻ CPU trong khi chúng ta đợi.
Khi bit bắt đầu đã được tạo, việc thực hiện tiếp tục ở dòng 115 để gửi địa chỉ Slave
và báo đọc/ghi.
Trong dòng 119 chúng ta lưu ý một lần nữa thời gian chờ khác. Dòng 120 đợi địa
chỉ I2C được gửi đi, trong khi dòng 121 kiểm tra thiết bị Slave có báo nhận yêu cầu.
Nếu không có thiết bị nào đáp ứng với địa chỉ được yêu cầu, một NAK sẽ được nhận
theo mặc định (nhờ điện trở kéo lên). Nếu hoạt động hết thời gian, một longjmp()
được thực hiện tại dòng 129.
Nếu hoạt động thành công, cờ sẽ bị xóa bằng cách gọi I2C_SR2() để đọc thanh ghi
trạng thái.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 23
Ghi I2C
Khi bit bắt đầu đã được tạo và địa chỉ được gửi, nếu chúng ta chỉ ra rằng ghi sau,
chúng ta phải làm điều đó tiếp theo. Bản kê 11-5 cho thấy hàm ghi được sử dụng.
Bản kê 11-5. Hàm Ghi I2C
0140: void
0141: i2c_write(I2C_Control *dev,uint8_t byte) {
0142: TickType_t t0 = systicks();
0143:
0144: i2c_send_data(dev->device,byte);
0145: while ( !(I2C_SR1(dev->device) & (I2C_SR1_BTF)) ) {
0146: if ( diff_ticks(t0,systicks()) > dev->timeout )
0147: longjmp(i2c_exception,I2C_Write_Timeout);
0148: taskYIELD();
0149: }
0150: }
Dòng 142 ghi lại thời gian cho thời gian chờ có thể xảy ra. Dòng 144 gửi byte dữ liệu
đến thiết bị ngoại vi I2C để được gửi tuần tự trên bus. Dòng 145 kiểm tra để hoàn
thành hoạt động này và hết thời gian với một longjmp() nếu cần thiết (dòng 147).
Ngoài việc chia sẻ CPU với taskYIELD(), hàm trả về khi thành công.
Đọc I2C
Nếu ý định là đọc, chương trình đọc được sử dụng để đọc một byte dữ liệu. Bản kê
11-6 minh họa code được sử dụng.
Bản kê 11-6. Hàm Đọc I2C
0157: uint8_t
0158: i2c_read(I2C_Control *dev,bool lastf) {
0159: TickType_t t0 = systicks();
0160:
0161: if ( lastf )
0162: i2c_disable_ack(dev->device); // Reading last/only byte
0163:
0164: while ( !(I2C_SR1(dev->device) & I2C_SR1_RxNE) ) {
0165: if ( diff_ticks(t0,systicks()) > dev->timeout )
0166: longjmp(i2c_exception,I2C_Read_Timeout);
0167: taskYIELD();
0168: }
0169:
0170: return i2c_get_data(dev->device);
0171: }
Một trong những khía cạnh khác thường của hàm i2c_read() được trình bày là nó
có một cờ Boolean lastf. Điều này được đặt là true bởi hàm gọi nếu nó là byte cuối
TRUNG TÂM ADVANCECAD
24 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
cùng hoặc duy nhất được đọc. Điều này cung cấp cho các thiết bị Slave một đầu vào
rằng nó có thể giảm (một số Slave phải tìm nạp trước dữ liệu để ở lại bước với bộ
điều khiển Master). Đây là mục đích của hàm gọi trên dòng 162.
Nếu không, đó là vấn đề kiểm tra trạng thái trong dòng 164 và hết thời gian trong
dòng 166 nếu hoạt động mất quá nhiều thời gian. Nếu không, CPU được chia sẻ với
taskYIELD() và byte được trả về trong dòng 170.
Khởi động lại I2C
Chương trình i2c_write_restart() được hiển thị một phần trong Bản kê 11-7 cung
cấp khả năng thay đổi từ một yêu cầu ghi vào yêu cầu khác (đọc hoặc viết) mà không
dừng lại. Bạn có thể tiếp tục với cùng một thiết bị Slave (bằng cách lặp lại cùng địa
chỉ Slave) hoặc chuyển sang một thiết bị khác. Điều này là quan trọng khi có nhiều
Master I2C vì điều này cho phép một tin nhắn khác mà không thông qua quyền truy
cập vào bus.
Bản kê 11-7. “Bí quyết” để Thực hiện một Giao tác I2C Restart
void
0179: i2c_write_restart(I2C_Control *dev,uint8_t byte,uint8_t addr) {
0180: TickType_t t0 = systicks();
0181:
0182: taskENTER_CRITICAL();
0183: i2c_send_data(dev->device,byte);
0184: // Must set start before byte has written out
0185: i2c_send_start(dev->device);
0186: taskEXIT_CRITICAL();
Một số loại thông tin khó có thể rút ra từ Tài liệu STM32 (RM0008). Tuy nhiên, chú
ý cẩn thận đến bản xuất và chú thích nhỏ đôi khi có thể mang lại giá trị lớn. Hướng
dẫn sử dụng cho biết:
Trong chế độ Master, thiết lập bit START khiến giao thức tạo ra một
điều kiện khởi động lại ở cuối đợt chuyển byte hiện thời.
Bằng cách tạo dòng 182 đến 186 một phần quan trọng, bạn đảm bảo rằng bạn yêu
cầu một “bắt đầu” khác trước khi ghi I2C hiện tại đang được hoàn thành.
Chương trình demo
Bản kê 11-8 minh họa vòng lặp chính của chương trình demo. Hầu hết nó đơn giản,
nhưng có một vài điều đáng chú ý. Sau khi thiết bị I2C được cấu hình trong dòng
131, vòng lặp bên trong bắt đầu tại dòng 134. Miễn là không có đầu vào bàn phím,
vòng lặp này tiếp tục ghi và đọc từ chip PCF8574.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 25
Bản kê 11-8. Vòng lặp chính của Chương trình demo
0116: static void
0117: task1(void *args __attribute__((unused))) {
0118: uint8_t addr = PCF8574_ADDR(0); // I2C Address
0119: volatile unsigned line = 0u; // Print line #
0120: volatile uint16_t value = 0u; // PCF8574P value
0121: uint8_t byte = 0xFF; // Read I2C byte
0122: volatile bool read_flag; // True if Interrupted
0123: I2C_Fails fc; // I2C fail code
0124:
0125: for (;;) {
0126: wait_start();
0127: usb_puts("nI2C Demo Begins "
0128: "(Press any key to stop)nn");
0129:
0130: // Configure I2C1
0131: i2c_configure(&i2c,I2C1,1000);
0132:
0133: // Until a key is pressed:
0134: while ( usb_peek() <= 0 ) {
0135: if ( (fc = setjmp(i2c_exception)) != I2C_Ok ) {
0136: // I2C Exception occurred:
0137: usb_printf("I2C Fail code %dnn",
fc,i2c_error(fc));
0138: break;
0139: }
0140:
0141: read_flag = wait_event(); // Interrupt or timeout
0142:
0143: // Left four bits for input, are set to 1-bits
0144: // Right four bits for output:
0145:
0146: value = (value & 0x0F) | 0xF0;
0147: usb_printf("Writing $%02X "
"I2C @ $%02Xn",value,addr);
0148: #if 0
0149: /*********************************************
0150: * This example performs a write transaction,
0151: * followed by a separate read transaction:
0152: *********************************************/
0153: i2c_start_addr(&i2c,addr,Write);
0154: i2c_write(&i2c,value&0x0FF);
0155: i2c_stop(&i2c);
0156:
0157: i2c_start_addr(&i2c,addr,Read);
0158: byte = i2c_read(&i2c,true);
0159: i2c_stop(&i2c);
0160: #else
0161: /*********************************************
0162: * This example performs a write followed
TRUNG TÂM ADVANCECAD
26 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
0163: * immediately by a read in one I2C transaction,
0164: * using a "Repeated Start"
0165: *********************************************/
0166: i2c_start_addr(&i2c,addr,Write);
0167: i2c_write_restart(&i2c,value&0x0FF,addr);
0168: byte = i2c_read(&i2c,true);
0169: i2c_stop(&i2c);
0170: #endif
0171: if ( read_flag ) {
0172: // Received an ISR interrupt:
0173: if ( byte & 0b10000000 )
0174: usb_printf("%04u: BUTTON RELEASED: "
0175: "$%02X; wrote $%02X, "
"ISR %dn",
0176: ++line,byte,
value,isr_count);
0177: else usb_printf("%04u: BUTTON PRESSED: "
0178: "$%02X; wrote $%02X, "
"ISR %dn",
0179: ++line,byte,
value,isr_count);
0180: } else {
0181: // No interrupt(s):
0182: usb_printf("%04u: "
"Read: $%02X, "
0183: "wrote $%02X, ISR %dn",
0184: ++line,byte,value,isr_count);
0185: }
0186: value = (value + 1) & 0x0F;
0187: }
0188:
0189: usb_printf("nPress any key to restart.n");
0190: }
0191: }
Lưu ý đặc biệt là setjmp() tại dòng 135. Vì C thiếu cơ chế ngoại lệ mà C++ sở hữu,
nên longjmp() được sử dụng thay thế. Việc thực hiện setjmp() của chúng ta ở đầu
vòng lặp cho phép chúng ta thực hiện một số hàm gọi I2C sau đó, mỗi hàm gọi có
điểm thất bại riêng, bao gồm cả thời gian chờ. Nếu bất kỳ lỗi nào xảy ra, longjmp()
sẽ đưa điều khiển trở lại dòng 135 và trả về code lỗi khác 0. Từ đó vấn đề có thể
được báo cáo và thoát ra khỏi vòng lặp bên trong.
Cơ chế setjmp/longjmp cũng có chút yêu cầu cần lưu ý. Chú ý rằng các biến line,
value và read_flag được đánh dấu dễ thay đổi (các dòng 119 đến 122). Điều này là
cần thiết để làm trình biên dịch ổn định vì nó cảnh báo về các giá trị đó đang được
thay đổi do kết quả của longjmp(), nếu nó xảy ra. setjmp tiết kiệm một loạt các thanh
ghi, trong khi longjmp phục hồi chúng để mang điều khiển trở lại. Bất kỳ biến nào
cũng được lưu trong bộ nhớ đệm sẽ bị ghi đè bởi longjmp.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 27
Có các câu lệnh #if, #else và #endif trong dòng 148, 160 và 170 tương ứng. Bằng cách
thay đổi dòng 148 từ giá trị 0 thành giá trị khác 0, tất cả các giao tác sẽ là đơn lẻ; tức
là, byte sẽ được ghi ra PCF8574P trong một giao tác, tiếp theo là một giao tác I2C
hoàn toàn riêng biệt để đọc từ nó.
Để dòng 148 ở giá trị 0 cho phép bạn kiểm tra hoạt động khởi động lại I2C. Các dòng
từ 166 đến 169 thực hiện một lệnh viết tiếp theo là đọc trong cùng một giao tác.
Phiên Demo
Thực hiện build từ đầu như sau:
$ make clobber
$ make
arm-none-eabi-gcc ... -o main.elf
arm-none-eabi-size main.elf
text data bss dec hex filename
13024 28 18200 31252 7a14 main.elf
Sẵn sàng cho thiết bị nạp flash và thực hiện các thao tác sau:
$ make flash
arm-none-eabi-objcopy -Obinary main.elf main.bin
/usr/local/bin/st-flash write main.bin 0x8000000
...
2017-12-09T21:32:12 INFO src/common.c: Flash written and verified!
jolly good!
Bây giờ, cắm cáp USB vào và khởi động minicom, như sau:
$ minicom usb
Welcome to minicom 2.7
OPTIONS:
Compiled on Sep 17 2016, 05:53:15.
Port /dev/cu.usbmodemWGDEM1, 21:33:40
Press Meta-Z for help on special keys
Task1 begun.
Press any key to begin.
Một lần nữa, đối số “usb” cho minicom là tên của file mà bạn đã lưu cài đặt minicom
của mình. Tôi đã sử dụng file có tên là usb trong ví dụ này.
Khi bạn thấy “Task1 begun”, hãy nhấn phím bất kỳ. Tôi nhấn Return (Enter). Khi
bạn làm điều đó, thiết bị I2C sẽ được cấu hình và bạn sẽ bắt đầu thấy các thông báo
có dạng sau:
I2C Demo Begins (Press any key to stop)
Writing $F0 I2C @ $20
TRUNG TÂM ADVANCECAD
28 cachdung.com - ungdungmaytinh.com
UNGDUNGMAYTINH.COM
0001: Read: $F0, wrote $F0, ISR 0
Writing $F1 I2C @ $20
0002: Read: $F1, wrote $F1, ISR 0
Nếu bạn nhấn phím một lần nữa, điều khiển sẽ dừng lại và sau đó thoát ra vòng lặp
ngoài. Nhấn phím một lần nữa sẽ khởi động lại bản demo ở vòng lặp trong.
Các giá trị được ghi ra cho PCF8574P sẽ tăng trong bốn bit thấp hơn. Nếu bạn gắn
LED vào P0 và P1 như trong sơ đồ, bạn sẽ thấy chúng được đếm ngược dưới dạng
nhị phân. Khi bạn nhấn nút, bạn sẽ thấy một số thông báo cho biết nút bấm và giải
phóng event.
Writing $F5 I2C @ $20
0006: Read: $F5, wrote $F5, ISR 0
Writing $F6 I2C @ $20
0007: Read: $F6, wrote $F6, ISR 0
Writing $F7 I2C @ $20
0008: BUTTON PRESSED: $77; wrote $F7, ISR 4
Writing $F8 I2C @ $20
0009: BUTTON PRESSED: $78; wrote $F8, ISR 4
Writing $F9 I2C @ $20
0010: BUTTON PRESSED: $79; wrote $F9, ISR 5
Writing $FA I2C @ $20
0011: BUTTON PRESSED: $7A; wrote $FA, ISR 6
Writing $FB I2C @ $20
0012: BUTTON PRESSED: $7B; wrote $FB, ISR 7
Writing $FC I2C @ $20
0013: BUTTON PRESSED: $7C; wrote $FC, ISR 8
Writing $FD I2C @ $20
0014: Read: $7D, wrote $FD, ISR 8
Writing $FE I2C @ $20
0015: BUTTON RELEASED: $FE; wrote $FE, ISR 11
Giá trị được hiển thị sau ISR cho bạn biết số lần chương trình ISR được gọi khi
PCF8574P chỉ báo ngắt. Nút của tôi khá là cũ, nó không nhả tốt, nên bạn thấy một
số event bấm nút. Lưu ý rằng trong khi nút được giữ lại, bit trên thay đổi từ bit-1
thành bit-0 (ví dụ, $FX thay đổi thành $7X).
Tóm tắt
Chương này giúp bạn chuẩn bị tốt cho công việc I2C. PCF8574 là một giải pháp rất
tiết kiệm để bổ sung thêm các cổng GPIO miễn là bạn không yêu cầu tốc độ cao.
Đồng thời, nó cung cấp cho bạn kinh nghiệm trong thế giới I2C. PCF8574 đã chứng
minh rằng nó có thể tạo ra các ngắt để bạn không phải liên tục kiểm tra các thay đổi
đường đầu vào. Điều này giúp giảm bớt gánh nặng của lưu lượng I2C trên bus.
TRUNG TÂM ADVANCECAD
cachdung.com - ungdungmaytinh.com 29

Más contenido relacionado

La actualidad más candente

Iot starter
Iot starterIot starter
Iot starterGreenCap
 
Bai giang atbmtt
Bai giang atbmttBai giang atbmtt
Bai giang atbmttHuynh MVT
 
Kien truc-co-ban-cua-stm32-arm-cortex-m3
Kien truc-co-ban-cua-stm32-arm-cortex-m3Kien truc-co-ban-cua-stm32-arm-cortex-m3
Kien truc-co-ban-cua-stm32-arm-cortex-m3Huynh MVT
 
E-book Wordpress
E-book WordpressE-book Wordpress
E-book WordpressHOSTVN
 
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...Nguyễn Hải Sứ
 
Giao trinhquantrimang[bookbooming.com]
Giao trinhquantrimang[bookbooming.com]Giao trinhquantrimang[bookbooming.com]
Giao trinhquantrimang[bookbooming.com]bookbooming1
 
Giao Trinh Lap Trinh Huong Doi Tuong
Giao Trinh Lap Trinh Huong Doi TuongGiao Trinh Lap Trinh Huong Doi Tuong
Giao Trinh Lap Trinh Huong Doi Tuongtrieulongnhi
 
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...Viết thuê báo cáo thực tập giá rẻ
 
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụng
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụngPhần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụng
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụngLac Viet Computing Corporation
 
Hướng Dẫn Sử Dụng Word 2010
Hướng Dẫn Sử Dụng Word 2010Hướng Dẫn Sử Dụng Word 2010
Hướng Dẫn Sử Dụng Word 2010Nguyễn Văn Mạnh
 
Thiet+lap+quan+tri+thu+dien+tu MDEAMON
Thiet+lap+quan+tri+thu+dien+tu MDEAMONThiet+lap+quan+tri+thu+dien+tu MDEAMON
Thiet+lap+quan+tri+thu+dien+tu MDEAMONlaonap166
 
Excel 2010 training book
Excel 2010 training bookExcel 2010 training book
Excel 2010 training bookTtx Love
 
Ccna căn bản bach khoa aptech
Ccna căn bản  bach khoa aptechCcna căn bản  bach khoa aptech
Ccna căn bản bach khoa aptechCamQueVuong
 
Giao trinh-asp-net-w2008
Giao trinh-asp-net-w2008Giao trinh-asp-net-w2008
Giao trinh-asp-net-w2008Son Duong Hoang
 

La actualidad más candente (19)

Iot starter
Iot starterIot starter
Iot starter
 
Bai giang atbmtt
Bai giang atbmttBai giang atbmtt
Bai giang atbmtt
 
Kien truc-co-ban-cua-stm32-arm-cortex-m3
Kien truc-co-ban-cua-stm32-arm-cortex-m3Kien truc-co-ban-cua-stm32-arm-cortex-m3
Kien truc-co-ban-cua-stm32-arm-cortex-m3
 
E-book Wordpress
E-book WordpressE-book Wordpress
E-book Wordpress
 
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...
tinh-toan-thiet-ke-va-mo-phong-he-thong-cap-phoi-tu-dong-su-dung-pheu-rung-va...
 
Giao trinhquantrimang[bookbooming.com]
Giao trinhquantrimang[bookbooming.com]Giao trinhquantrimang[bookbooming.com]
Giao trinhquantrimang[bookbooming.com]
 
Giao trinh ngon ngu lap trinh c#
Giao trinh ngon ngu lap trinh c#Giao trinh ngon ngu lap trinh c#
Giao trinh ngon ngu lap trinh c#
 
Giao Trinh Lap Trinh Huong Doi Tuong
Giao Trinh Lap Trinh Huong Doi TuongGiao Trinh Lap Trinh Huong Doi Tuong
Giao Trinh Lap Trinh Huong Doi Tuong
 
Excel 2010
Excel 2010Excel 2010
Excel 2010
 
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...
Đồ án điện tử viễn thông Giải pháp truyền tải IP trên quang cho mạng viễn thô...
 
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụng
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụngPhần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụng
Phần mềm kế toán Cloud AccNetC - Tài liệu hướng dẫn sử dụng
 
Hướng Dẫn Sử Dụng Word 2010
Hướng Dẫn Sử Dụng Word 2010Hướng Dẫn Sử Dụng Word 2010
Hướng Dẫn Sử Dụng Word 2010
 
Thiet+lap+quan+tri+thu+dien+tu MDEAMON
Thiet+lap+quan+tri+thu+dien+tu MDEAMONThiet+lap+quan+tri+thu+dien+tu MDEAMON
Thiet+lap+quan+tri+thu+dien+tu MDEAMON
 
Excel 2010 training book
Excel 2010 training bookExcel 2010 training book
Excel 2010 training book
 
Tai lieu huong_dan_microsoft_word_2010
Tai lieu huong_dan_microsoft_word_2010Tai lieu huong_dan_microsoft_word_2010
Tai lieu huong_dan_microsoft_word_2010
 
Đề tài: Ứng dụng lập trình điều khiển động cơ bước sử dụng chip
Đề tài: Ứng dụng lập trình điều khiển động cơ bước sử dụng chipĐề tài: Ứng dụng lập trình điều khiển động cơ bước sử dụng chip
Đề tài: Ứng dụng lập trình điều khiển động cơ bước sử dụng chip
 
Ccna căn bản bach khoa aptech
Ccna căn bản  bach khoa aptechCcna căn bản  bach khoa aptech
Ccna căn bản bach khoa aptech
 
Giao trinh-asp-net-w2008
Giao trinh-asp-net-w2008Giao trinh-asp-net-w2008
Giao trinh-asp-net-w2008
 
Luận văn: Vận hành, quản lý, giám sát hệ thống BTS Viettel, HAY
Luận văn: Vận hành, quản lý, giám sát hệ thống BTS Viettel, HAYLuận văn: Vận hành, quản lý, giám sát hệ thống BTS Viettel, HAY
Luận văn: Vận hành, quản lý, giám sát hệ thống BTS Viettel, HAY
 

Similar a [Demo] Begin STM32 vol-2

Giáo trình Quản trị mạng
Giáo trình Quản trị mạngGiáo trình Quản trị mạng
Giáo trình Quản trị mạngTran Tien
 
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]bookbooming1
 
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]bookbooming1
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#Xuan Le
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#Le Trong Linh
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#thanh nguyen
 
04. de cuong thiet lap va cau hinh mang lan (3 tc)
04. de cuong   thiet lap va cau hinh mang lan (3 tc)04. de cuong   thiet lap va cau hinh mang lan (3 tc)
04. de cuong thiet lap va cau hinh mang lan (3 tc)Đinh Luận
 
Bao cao do an
Bao cao do an Bao cao do an
Bao cao do an Thao Thao
 
Bai giang asp.net full
Bai giang asp.net fullBai giang asp.net full
Bai giang asp.net fullBoom Su
 
Bai giang asp.net full
Bai giang asp.net fullBai giang asp.net full
Bai giang asp.net fullLy hai
 
Thiet ke lan_wan
Thiet ke lan_wanThiet ke lan_wan
Thiet ke lan_wanHuu Phan
 
Thiet ke lan_wan
Thiet ke lan_wanThiet ke lan_wan
Thiet ke lan_wanGió Lào
 
Giao trinh quan tri mang&thietbimang
Giao trinh quan tri mang&thietbimangGiao trinh quan tri mang&thietbimang
Giao trinh quan tri mang&thietbimangLe Ngoc Thanh
 
Giao trình asp-net w2008
Giao trình asp-net w2008 Giao trình asp-net w2008
Giao trình asp-net w2008 Tùng Trần
 
Giáo trình ASP.NET - Trung tâm Nhất Nghệ
Giáo trình ASP.NET - Trung tâm Nhất NghệGiáo trình ASP.NET - Trung tâm Nhất Nghệ
Giáo trình ASP.NET - Trung tâm Nhất NghệTrung Thanh Nguyen
 
Linq vnese
Linq vneseLinq vnese
Linq vnesechienhm
 

Similar a [Demo] Begin STM32 vol-2 (20)

Giáo trình Quản trị mạng
Giáo trình Quản trị mạngGiáo trình Quản trị mạng
Giáo trình Quản trị mạng
 
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
 
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]Giáo trình lập trình mạng   đh đà lạt[bookbooming.com]
Giáo trình lập trình mạng đh đà lạt[bookbooming.com]
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#
 
Lap trinh website dotnet c#
Lap trinh website dotnet c#Lap trinh website dotnet c#
Lap trinh website dotnet c#
 
04. de cuong thiet lap va cau hinh mang lan (3 tc)
04. de cuong   thiet lap va cau hinh mang lan (3 tc)04. de cuong   thiet lap va cau hinh mang lan (3 tc)
04. de cuong thiet lap va cau hinh mang lan (3 tc)
 
Bao cao do an
Bao cao do an Bao cao do an
Bao cao do an
 
Tài liệu CCNA - Lưu hành nội bộ
Tài liệu CCNA  - Lưu hành nội bộTài liệu CCNA  - Lưu hành nội bộ
Tài liệu CCNA - Lưu hành nội bộ
 
Bai giang asp.net full
Bai giang asp.net fullBai giang asp.net full
Bai giang asp.net full
 
Bai giang asp.net full
Bai giang asp.net full Bai giang asp.net full
Bai giang asp.net full
 
Bai giang asp.net full
Bai giang asp.net fullBai giang asp.net full
Bai giang asp.net full
 
Baigiang ltm
Baigiang ltmBaigiang ltm
Baigiang ltm
 
Thiet ke lan_wan
Thiet ke lan_wanThiet ke lan_wan
Thiet ke lan_wan
 
Thiet ke lan_wan
Thiet ke lan_wanThiet ke lan_wan
Thiet ke lan_wan
 
Giao trinh quan tri mang&thietbimang
Giao trinh quan tri mang&thietbimangGiao trinh quan tri mang&thietbimang
Giao trinh quan tri mang&thietbimang
 
Giao trình asp-net w2008
Giao trình asp-net w2008 Giao trình asp-net w2008
Giao trình asp-net w2008
 
Giáo trình ASP.NET - Trung tâm Nhất Nghệ
Giáo trình ASP.NET - Trung tâm Nhất NghệGiáo trình ASP.NET - Trung tâm Nhất Nghệ
Giáo trình ASP.NET - Trung tâm Nhất Nghệ
 
Linq vnese
Linq vneseLinq vnese
Linq vnese
 
Luận Văn Kiến Trúc Hệ Thống Của Arm Cortex.doc
Luận Văn Kiến Trúc Hệ Thống Của Arm Cortex.docLuận Văn Kiến Trúc Hệ Thống Của Arm Cortex.doc
Luận Văn Kiến Trúc Hệ Thống Của Arm Cortex.doc
 

[Demo] Begin STM32 vol-2

  • 1. UNGDUNGMAYTINH.COM MỤC LỤC Chương 11 I2C .................................................................................................................. 9 Bus I2C ........................................................................................................................... 9 Master và Slave .......................................................................................................... 9 Start và Stop.............................................................................................................. 10 Bit Dữ liệu................................................................................................................. 11 Địa chỉ I2C ................................................................................................................ 11 Giao tác I2C (I2C Transaction).............................................................................. 12 Chip mở rộng PCF8574 GPIO ............................................................................... 13 Mạch I2C ...................................................................................................................... 14 Đường PCF8574 INT .............................................................................................. 15 Cấu hình PCF8574 .................................................................................................... 16 Điều khiển GPIO của PCF8574............................................................................. 17 Tạo dạng sóng .......................................................................................................... 18 Mạch demo.................................................................................................................. 18 Ngắt EXTI.................................................................................................................. 19 Phần mềm I2C ........................................................................................................... 21 Kiểm tra I2C Sẵn sàng............................................................................................. 22 Bắt đầu I2C................................................................................................................ 22 Ghi I2C....................................................................................................................... 24 Đọc I2C ...................................................................................................................... 24 Khởi động lại I2C..................................................................................................... 25 Chương trình demo .................................................................................................. 25 Phiên Demo .............................................................................................................. 28 Tóm tắt ......................................................................................................................... 29 Chương 12 OLED ........................................................................................................... 31 Màn hình OLED .......................................................................................................... 31 Cấu hình.................................................................................................................... 32 Kết nối Màn hình..................................................................................................... 33 Tính năng hiển thị..................................................................................................... 34 Sơ đồ demo.................................................................................................................. 35
  • 2. AFIO................................................................................................................................35 Đồ họa............................................................................................................................37 Pixmap ........................................................................................................................39 Ghi Pixmap................................................................................................................40 Phần mềm Vôn-kế....................................................................................................41 Mô-đun Main ............................................................................................................42 Demo ..............................................................................................................................44 Tóm tắt ..........................................................................................................................45 Chương 13 OLED Dùng DMA.......................................................................................47 Thách thức....................................................................................................................47 Mạch............................................................................................................................47 Hoạt động DMA...........................................................................................................47 Thực thi DMA...........................................................................................................48 Demo ..............................................................................................................................52 Khởi tạo DMA...........................................................................................................53 Khởi động DMA.......................................................................................................54 Tác vụ Quản lý SPI/DMA OLED...........................................................................54 Chương trình DMA ISR..........................................................................................57 Khởi động lại chuyển DMA...................................................................................58 Thực thi Demo.............................................................................................................59 Những thách thức khác ...........................................................................................60 Tóm tắt ..........................................................................................................................61 Chương 14 Analog-to-Digital Conversion ................................................................63 Nguồn STM32F103C8T6..........................................................................................63 Demo ..............................................................................................................................64 Đầu vào Analog PA0 và PA1..................................................................................64 Cấu hình ngoại vi ADC...........................................................................................64 Chạy Demo ...................................................................................................................67 Đọc ADC ....................................................................................................................68 Điện áp Analog............................................................................................................70 Tóm tắt ..........................................................................................................................72
  • 3. UNGDUNGMAYTINH.COM Chương 15 Hệ thống Xung.......................................................................................... 73 Mở đầu .......................................................................................................................... 73 Mạch Dao động RC ................................................................................................. 74 Dao động Thạch anh............................................................................................... 75 Công suất Dao động................................................................................................ 75 Xung Thời gian thực................................................................................................. 76 Xung Watchdog ......................................................................................................... 76 Xung Hệ thống (SYSCLK)....................................................................................... 76 SYSCLK và USB....................................................................................................... 79 Bus AHB........................................................................................................................ 80 rcc_clock_setup_in_hse_8mhz_out_72mhz()...................................................... 81 Thiết bị Ngoại vi APB1........................................................................................... 84 Thiết bị Ngoại vi APB2........................................................................................... 84 Timer (bộ định thời)................................................................................................ 84 rcc_set_mco()............................................................................................................ 84 Bản demo HSI ............................................................................................................ 85 Bản demo HSE............................................................................................................ 86 Bản demo PLL ÷ 2..................................................................................................... 87 Tóm tắt ......................................................................................................................... 88 Chương 16 PWM với Timer 2 ...................................................................................... 89 Tín hiệu PWM.............................................................................................................. 89 Timer 2.......................................................................................................................... 90 Vòng lặp PWM............................................................................................................ 93 Tính toán Prescale Timer ....................................................................................... 93 Tần số 30 Hz.............................................................................................................. 94 Đấu nối Servo............................................................................................................. 95 Chạy Demo .................................................................................................................. 96 PWM trên PB3 ............................................................................................................ 96 Các Timer Khác .......................................................................................................... 97 Kênh PWM khác...................................................................................................... 98 Tóm tắt ......................................................................................................................... 98
  • 4. Chương 17 Input PWM với Timer 4 ............................................................................99 Tín hiệu Servo .............................................................................................................99 Điện áp tín hiệu ........................................................................................................100 Dự án Demo...............................................................................................................100 Cấu hình GPIO .......................................................................................................100 Cấu hình Timer 4....................................................................................................100 Vòng lặp Task1 .......................................................................................................102 Chương trình ISR ...................................................................................................102 Chạy Demo .................................................................................................................103 Đầu ra Phiên (Session Output)............................................................................105 Đầu vào Timer...........................................................................................................106 Tóm tắt ........................................................................................................................107 Chương 18 Bus CAN....................................................................................................109 CAN Bus.......................................................................................................................109 Tín hiệu vi sai ............................................................................................................111 Trội/lặn .....................................................................................................................112 Phân xử Bus...............................................................................................................113 Đồng bộ hóa ............................................................................................................114 Định dạng Tin nhắn...............................................................................................114 Giới hạn STM32.........................................................................................................116 Demo ............................................................................................................................116 Build Phần mềm .....................................................................................................116 Giao diện UART.....................................................................................................117 Nạp flash cho MCU................................................................................................117 Demo Bus.................................................................................................................118 Phiên Chạy..................................................................................................................119 Tin nhắn CAN.........................................................................................................121 Đồng bộ....................................................................................................................121 Tóm tắt ........................................................................................................................121 Chương 19 Phần mềm Bus CAN...............................................................................123 Khởi tạo .......................................................................................................................123
  • 5. UNGDUNGMAYTINH.COM can_init().................................................................................................................. 125 Các bộ lọc Nhận CAN........................................................................................... 126 Các ngắt Nhận CAN.............................................................................................. 127 Nhận Ứng dụng ..................................................................................................... 130 Gửi Tin nhắn CAN................................................................................................ 132 Tóm tắt ....................................................................................................................... 133 Chương 20 Dự án Mới................................................................................................. 135 Tạo Dự án................................................................................................................... 135 Makefile .................................................................................................................. 136 Bao gồm Makefiles................................................................................................ 138 Header Phụ thuộc .................................................................................................. 138 Tùy chọn biên dịch................................................................................................ 138 Nạp flash 128k........................................................................................................ 139 FreeRTOS ................................................................................................................... 139 rtos/opencm3.c........................................................................................................ 139 rtos/heap_4.c ........................................................................................................... 140 Mô-đun bắt buộc.................................................................................................... 141 FreeRTOSConfig.h................................................................................................... 141 Thư viện Người dùng............................................................................................. 143 Lỗi Rookie.................................................................................................................. 144 Tóm tắt ....................................................................................................................... 144 Chương 21 Xử lý Sự cố.............................................................................................. 145 Gnu GDB..................................................................................................................... 145 Máy chủ GDB......................................................................................................... 145 GDB từ xa................................................................................................................ 146 Giao diện Người dùng Văn bản GDB............................................................... 149 Sự cố Ngoại vi GPIO............................................................................................... 150 Chức năng Thay thế thất bại .............................................................................. 151 Lỗi ngoại vi ................................................................................................................ 151 ISR FreeRTOS Crash .............................................................................................. 152 Stack Overflow......................................................................................................... 152
  • 6. Ước tính Kích thước Stack....................................................................................153 Khi một Debugger không trợ giúp.....................................................................153 Push/Pull hoặc Cực máng Mở.............................................................................154 Lỗi Ngoại vi ................................................................................................................154 Tài liệu .........................................................................................................................154 libopencm3 ..............................................................................................................155 Các ưu tiên của Tác vụ FreeRTOS......................................................................156 Tạo lịch trình trong libopencm3..........................................................................157 Tóm tắt ........................................................................................................................158
  • 7. UNGDUNGMAYTINH.COM Chương 11 I2C Bus I2C là một hệ thống phần cứng tiện lợi bởi vì nó chỉ sử dụng hai dây để giao tiếp. Bus cũng được biết đến với các tên khác, chẳng hạn như IIC (inter-integrated circuit: liên mạch tích hợp) hoặc TWI (two-wire interface: giao diện hai dây). Phillips Semiconductor đã phát triển bus I2C, sau đó Intel mở rộng với giao thức SMBus. Đây là các giao thức tương tự nhau, nhưng tôi sẽ tập trung vào I2C trong chương này. Với tiện ích của bus I2C, không có gì ngạc nhiên khi nền tảng STM32 bao gồm phần cứng ngoại vi cho nó. Chương này sẽ khám phá cách sử dụng thiết bị ngoại vi kết nối với thiết bị mở rộng GPIO PCF8574 được gắn vào bus. Bus I2C Một trong những điểm nổi bật của một bus truyền thông nối tiếp I2C là nó chỉ sử dụng hai dây. Nguồn cung cấp và kết nối với đất không được bao gồm trong phần này. Hai đường truyền liên quan như sau: • Xung hệ thống (System Clock, thường được gắn nhãn SCL) • Dữ liệu hệ thống (System Data, thường được gắn nhãn SDA) Mỗi dây này nằm ở mức điện áp cao (thường là 5 hoặc 3,3V). Bất kỳ thiết bị nào trên bus đều có thể tạo ra tín hiệu dữ liệu bằng cách kéo dây xuống mức low (0 V). Điều này hoạt động tốt cho các transistor cực góp mở (lưỡng cực) hoặc cực máng mở (FET). Khi transistor hoạt động, chúng hoạt động giống như một công tắc làm ngắn dòng bus xuống đất. Khi bus không được kết nối, một điện trở kéo lên làm điện áp của đường dây ở mức high. Vì lý do này, cả hai dây I2C hoạt động với ít nhất một điện trở kéo lên. Master và Slave Với mỗi thiết bị trên bus có thể kéo các dây xuống mức low, phải có một số loại giao thức để giữ mọi thứ được ngăn nắp. Nếu không, trên bus sẽ có nhiều mẩu tin giao tiếp truyền đi mà không có đầu nhận nào biết được gì. Vì lý do này, giao thức I2C thường sử dụng một thiết bị Master và nhiều thiết bị Slave. Trong các hệ thống phức TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 9
  • 8. tạp hơn, có thể có nhiều hơn một bộ điều khiển Master, nằm ngoài phạm vi của chương này. Thiết bị Master luôn bắt đầu giao tiếp và điều khiển tín hiệu xung. Ngoại lệ cho dây SCL đang được điều khiển bởi những phần Slave đôi khi có thể kéo dài xung để cấp thêm thời gian (khi nó được Master hỗ trợ). Xung kéo dài xảy ra khi thiết bị Slave tiếp tục giữ dây SCL ở mức low sau khi Master đã giải phóng nó. Các thiết bị Slave chỉ phản hồi khi được nói đến. Mỗi slave có một địa chỉ thiết bị 7- bit duy nhất để nó biết khi một tin nhắn bus đã được gửi đến nó. Đây là một khía cạnh mà I2C khác với bus SPI. Mỗi thiết bị I2C được gắn địa chỉ bởi một byte địa chỉ, trong khi các thiết bị SPI được chọn bởi một dây chọn chip. Start và Stop I2C không hoạt động khi cả hai đường SDA và SCL đều ở mức high. Trong trường hợp này, không có thiết bị - Master hoặc Slave - làm các bus ở mức low. Sự bắt đầu của một giao tác I2C được chỉ định bởi các event sau: 1. Dây SCL vẫn ở mức high. 2. Dây SDA bị kéo xuống mức low. Bước hai thường xảy ra trong một chu kỳ xung, mặc dù nó không cần phải chính xác như vậy. Khi bus không hoạt động, đủ để thấy dây SDA xuống mức thấp trong khi SCL vẫn ở mức high. Hình 11-1 minh họa tín hiệu I2C bắt đầu, dừng và lặp lại. Hình 11-1. I2C bắt đầu, dừng và lặp lại tín hiệu bit bắt đầu Chế độ repeated start vừa tối ưu hóa stop và start, vừa là một cách để giữ bus trong khi tiếp tục một giao tác I2C dài hơn. Chúng ta sẽ thảo luận thêm về điều này sau. TRUNG TÂM ADVANCECAD 10 cachdung.com - ungdungmaytinh.com
  • 9. UNGDUNGMAYTINH.COM Bit Dữ liệu Các bit dữ liệu được truyền đi cùng với tín hiệu chuyển tiếp từ cao đến thấp trong tín hiệu xung (SCL). Hình 11-2 minh họa. Hình 11-2. Tín hiệu bit dữ liệu I2C Việc lấy mẫu bus SDA xảy ra khi các mũi tên được hiển thị. Mức high hoặc low của dây SDA được đọc tại thời điểm mà dây SCL được kéo xuống mức low (bởi Master). Địa chỉ I2C Trước khi chúng ta xem xét toàn bộ giao tác bus, hãy mô tả byte địa chỉ, được sử dụng để xác định thiết bị slave sẽ đáp ứng (Hình 11-3). Ngoài các bit địa chỉ, bit đọc/ghi cho biết ý định đọc hoặc ghi từ/đến thiết bị Slave. Hình 11-3. Định dạng địa chỉ 7-bit I2C 7 bit địa chỉ được dịch chuyển lên 1 bit trong byte địa chỉ, trong khi bit đọc/ghi ở bên phải. Bit đọc/ghi được định nghĩa như sau: • bit-1 cho biết thao tác đọc từ thiết bị Slave sẽ sử dụng • bit-0 cho biết thao tác ghi vào thiết bị Slave sẽ sử dụng Địa chỉ và bit đọc/ghi luôn theo một bit bắt đầu hoặc lặp lại bắt đầu trên bus I2C. Bit bắt đầu yêu cầu bộ điều khiển I2C để kiểm tra rằng bus không được sử dụng bởi một Master khác; nó thực hiện điều này bằng cách sử dụng một thủ tục xem xét bus (khi đa-Master được hỗ trợ). Nhưng khi truy cập bus thành công, bus được sở hữu bởi bộ điều khiển cho đến khi nó được xuất với một bit dừng. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 11
  • 10. Việc bắt đầu lặp lại cho phép giao thức hiện tại tiếp tục mà không cần xem xét bus. Vì một địa chỉ và bit đọc/ghi phải tuân thủ, điều này cho phép nhiều Slave được hỗ trợ với một giao tác. Ngoài ra, cùng một Slave có thể được giải quyết nhưng được truy cập với một chế độ đọc/ghi khác. Mẹo Đôi khi mọi người báo cáo rằng các địa chỉ Slave được dịch chuyển lên một bit khi chúng được gửi đi. Điều này có tác dụng nhân địa chỉ cho hai. Địa chỉ 0x42 khi chuyển sang phải trở thành 0x21. Xem điều này trong tài liệu. Giao tác I2C (I2C Transaction) Hình 11-4 minh họa một giao tác ghi và đọc (không sử dụng bắt đầu lặp lại). Hình 11-4. Giao tác ghi và giao tác đọc I2C Phần trên của Hình 11-4 minh họa một giao tác ghi đơn giản. Chuỗi cơ bản của event để viết minh họa như sau: 1. Bộ điều khiển I2C điều khiển bus và phát ra bit khởi động. 2. Bộ điều khiển (Master) ghi ra 7 bit địa chỉ theo sau là một bit-0, chỉ ra rằng đây sẽ là một giao tác ghi. 3. Thiết bị Slave báo nhận yêu cầu và kéo dây data xuống mức low trong bit ACK (acknowledge: báo nhận). Nếu không có Slave đáp ứng, dây data sẽ ở mức high và tạo ra một NAK (negative acknowledge: báo nhận âm) để được nhận bởi bộ điều khiển. 4. Bởi vì đây là một giao tác ghi, byte dữ liệu được ghi ra. TRUNG TÂM ADVANCECAD 12 cachdung.com - ungdungmaytinh.com
  • 11. UNGDUNGMAYTINH.COM 5. Thiết bị slave báo nhận việc nhận byte dữ liệu bằng cách kéo dây data xuống mức low trong thời gian bit ACK. 6. Master không gửi thêm dữ liệu, nên nó ghi một bit dừng và giải phóng bus I2C. Yêu cầu đọc cũng tương tự: 1. Bộ điều khiển I2C điều khiển bus và phát ra bit khởi động. 2. Bộ điều khiển (Master) ghi ra bảy bit địa chỉ theo sau là bit-1, cho biết đây sẽ là một giao tác đọc. 3. Thiết bị Slave báo nhận yêu cầu và kéo dây data xuống mức low trong bit ACK. Nếu không có Slave đáp ứng, dây data sẽ ở mức high và NAK sẽ được bộ điều khiển nhận. 4. Bởi vì đây là một giao tác đọc, Master tiếp tục ghi ra các bit xung để cho phép thiết bị Slave đồng bộ hóa dữ liệu của nó để phản hồi cho Master. 5. Với mỗi xung clock, thiết bị Slave ghi ra tám byte dữ liệu vào bộ điều khiển Master. 6. Trong thời gian ACK, bộ điều khiển Master thường gửi NAK khi không có thêm byte nào được đọc. 7. Bộ điều khiển gửi bit dừng, luôn luôn kết thúc giao thức với Slave (bất kể ACK/NAK cuối cùng đã gửi). Chip mở rộng PCF8574 GPIO Để thực hành bus I2C trong chương này, chúng ta sẽ sử dụng chip mở rộng PCF8574 GPIO (Hình 11-5). Đây là một chip tuyệt vời để thêm các dây GPIO bổ sung, miễn là bạn không cần tốc độ cao (bản demo vận hành bus I2C ở 100 kHz). Hình 11-5. Sơ đồ chân của PCF8574P TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 13
  • 12. Điện áp +3.3V được áp dụng cho chân 16, trong khi kết nối nối đất là chân 8. Chân A0 đến A2 được sử dụng để chọn địa chỉ Slave của chip (Bảng 11-1). Chân P0 đến P7 là các chân dữ liệu GPIO, có thể là đầu vào hoặc đầu ra. Chân 14 kết nối với xung (SCL), trong khi chân 15 kết nối với đường data (SDA). Chân 13 có thể được sử dụng để thông báo. Bảng 11-1. Cấu hình Địa chỉ PCF8574 A0 A1 A2 Địa chỉ PCF8574 Địa chỉ PCF8574A 0 0 0 0x20 0x38 0 0 1 0x21 0x39 0 1 0 0x22 0x3A 0 1 1 0x23 0x3B 1 0 0 0x24 0x3C 1 0 1 0x25 0x3D 1 1 0 0x26 0x3E 1 1 1 0x27 0x3F Các dòng địa chỉ A0 đến A2 được lập trình thành 0 khi được nối đất và thành các bit-1 khi được kết nối với Vcc (+3.3V trong bản demo này). Nếu bạn có chip PCF8575A, thì địa chỉ sẽ được lấy từ cột bên phải. Chip PCF8574 trước đó sử dụng địa chỉ thập lục phân ở cột bên trái của bảng. Mạch I2C Hình 11-6 minh họa ba thiết bị PCF8574P gắn vào STM32 thông qua bus I2C. TRUNG TÂM ADVANCECAD 14 cachdung.com - ungdungmaytinh.com
  • 13. UNGDUNGMAYTINH.COM Hình 11-6. STM32 nối với ba thiết bị Slave PCF8574P sử dụng bus I2C Sơ đồ hơi nhiều dây nối, nhưng nó dễ hình dung. Lưu ý rằng bus I2C chỉ bao gồm một cặp dây, SCL và SDA, xuất phát từ STM32. Hai dây này được kéo lên mức high bởi các điện trở R1 và R2. Mỗi thiết bị Slave cũng được kết nối với các đường bus này, cho phép mỗi thiết bị này phản hồi khi nó nhận ra địa chỉ Slave của nó. Chú ý rằng IC1, IC2 và IC3 có hệ thống nối dây khác nhau cho các chân địa chỉ A0, A1 và A2. Điều này cấu hình mỗi thiết bị để đáp ứng với một địa chỉ Slave khác nhau (xem Bảng 11-1). Các địa chỉ này phải là duy nhất. Đường PCF8574 INT Các kết nối còn lại trong Hình 11-6 là nguồn và đường INT . Đường INT là một thành phần bus tùy chọn không liên quan gì đến bus I2C. Bạn có thể không cần gắn tất cả các thiết bị PCF8574P vào đường INT nếu chúng không được sử dụng cho đầu vào GPIO. Đường INT cho biết rằng GPIO đầu vào đã thay đổi và được gắn vào đường ngắt vi xử lý. Điều này giúp tiết kiệm MCU từ việc liên tục sử dụng các thiết bị I2C để xem liệu một nút đã được nhấn chưa. Nếu bất kỳ đầu vào nào thay đổi từ mức cao xuống thấp hoặc thấp đến cao, thì transistor trong PCF8574 được kích hoạt và kéo đường INT xuống mức low. Nó sẽ ở mức low cho đến khi thiết bị có “dịch vụ” ngắt. Một thao tác đọc hoặc ghi đơn giản tới thiết bị ngoại vi là tất cả những gì cần thiết để phục vụ ngắt. Dây INT không xác định thiết bị Slave nào đã đăng ký thay đổi. MCU vẫn phải kiểm tra các thiết bị Slave tham gia để xem sự thay đổi xảy ra ở đâu. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 15
  • 14. Điều quan trọng cần lưu ý là có một giới hạn nhỏ. Nếu thay đổi mức GPIO xảy ra quá nhanh, sẽ không có ngắt nào được tạo ra. Cũng có thể xảy ra event thay đổi GPIO trong chu kỳ ACK/NAK khi ngắt được xóa. Một ngắt xảy ra sau đó cũng có thể bị mất. Datasheet của NXP (hãng NXP Semiconductors) chỉ ra rằng phải mất 4 μs từ một thay đổi GPIO được nhận biết đến lúc kích hoạt dây INT . Thời gian còn lại sẽ bao gồm đáp ứng ngắt và xử lý phần mềm của MCU. Cấu hình PCF8574 Datasheet từ hãng NXP Semiconductors mô tả các cổng I/O như quasi-bidirectional (gần như hai chiều). Điều này có nghĩa là các cổng GPIO (P0 đến P7) có thể được sử dụng làm output hoặc được đọc trực tiếp như input, mà không cần bất kỳ cấu hình nào thông qua thanh ghi thiết bị. Để gửi một giá trị đầu ra, bạn chỉ cần ghi vào thiết bị PCF8574 qua bus I2C. Mặt khác, đầu vào GPIO yêu cầu một mẹo nhỏ - nơi bạn cần đầu vào GPIO, trước hết bạn ghi bit-1 vào cổng GPIO. Để xem cách thức hoạt động, xem lại Hình 11-7. Hình 11-7. Mạch GPIO đơn giản PCF8574 Bắt đầu ở phía trên cùng của sơ đồ nơi đặt Vcc (+3.3 V). Bên trong chip là một nguồn- dòng 100 μA nối tiếp với các transistor M2 và M1. Do đó, khi một bit cao (bit-1) được ghi vào cổng GPIO, transistor M2 được bật và M1 bị tắt (được điều khiển bởi “điều khiển hi/lo” bên trong chip). Transistor M3 đang tắt tại thời điểm này. Nếu bạn nối GPIO xuống đất, nguồn-dòng giới hạn dòng điện đến 100 μA khi nó đi qua M2 và ra khỏi chân GPIO xuống đất (mũi tên phải trong Hình 11-7). Trong khi đó, bên trong của PCF8574 có thể nhận ra mức low trên “Read Input” bên trong TRUNG TÂM ADVANCECAD 16 cachdung.com - ungdungmaytinh.com
  • 15. UNGDUNGMAYTINH.COM được nối với GPIO, được đọc ngược lại như là một bit-0. Bằng cách ghi bit-1 cho GPIO, bạn cho phép một mạch bên ngoài kéo áp xuống mức low, hoặc để nó ở mức high. Dòng điện luôn giới hạn ở mức 100 μA, vì vậy không có tác hại gì xảy ra. Nếu, thay vào đó, chân GPIO được ghi là bit-0, transistor M1 sẽ luôn được bật, làm đoản mạch GPIO. Kết quả là “Read Input” sẽ luôn luôn nhận bit-0. Theo quy tắc đơn giản là viết bit-1 cho GPIO, bạn có thể nhận ra được khi nào nó được nối xuống đất làm đầu vào. Điều khiển GPIO của PCF8574 Thiết kế gần như hai chiều của GPIO có một hệ quả. Bạn đã thấy rằng đầu ra GPIO bị đoản mạch được hạn dòng ở 100 μA. Điều này có nghĩa là GPIO không thể hoạt động như một nguồn cấp dòng cho một LED. Một LED điển hình cần dòng điện khoảng 10mA, gấp 100 lần so với GPIO này có khả năng cung cấp! Hình 11-8. Điều khiển tải dòng cao hơn với PCF8574 Tuy nhiên, transistor M1 có thể xử lý tối đa 25 mA nếu bạn sử dụng chân GPIO để xả nguồn cho LED. Hình 11-8 minh họa cách điều khiển một LED. LED và điện trở R1 được cấp nguồn từ Vcc, với dòng không bị giới hạn. Vì vậy, M1 hoạt động như một công tắc để xả dòng điện xuống đất, bật sáng LED. Tác động nguồn của điều này là bạn cần phải viết một bit-0 để bật LED. Lưu ý Dù chế độ điều khiển ở mức cao của PCF8574 bị giới hạn ở 100 μA, điều này là đủ để điều khiển các đầu vào tín hiệu CMOS khác. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 17
  • 16. Tạo dạng sóng Khi đầu ra GPIO được viết dưới dạng bit-1, chỉ có dòng điện 100 μA có sẵn để kéo nó lên tới Vcc. Điều này trình bày một vấn đề nhỏ khi nó hiện đang ở điện thế thấp, dẫn đến một thời gian tăng chậm. Các nhà thiết kế của PCF8574 bao gồm một mạch với transistor M3 thường tắt (Hình 11-8). Tuy nhiên, khi thiết bị được ghi vào, mỗi GPIO nhận một bit-1 được tăng từ M3 trong chu kỳ I2C ACK/NAK. Điều này giúp cung cấp sự chuyển đổi từ thấp đến cao một cách nhanh chóng trên các đầu ra. Khi chu kỳ ACK/NAK hoàn tất, M3 sẽ tắt một lần nữa, để lại giới hạn dòng điện 100 μA để duy trì đầu ra ở mức cao. Mạch demo Hình 11-9 minh họa mạch cuối cùng cho chương trình demo. Những thay đổi đáng chú ý là chỉ có một chip PCF8574 được sử dụng, cùng với hai LED và một nút nhấn. Hình 11-9. I2C demo với LED và nút nhấn Khi nối dây mạch này, đừng quên nối điện trở kéo lên R3 sao cho điện thế không sử dụng của GPIO PC14 cao. Cũng lưu ý rằng cả hai LED đều được cung cấp từ dòng Vcc sao cho các cổng P0 và P1 xả dòng điện để bật sáng các LED. Cổng P7 sẽ đọc nút ấn, thường nó sẽ ở mức cao (nhớ lại rằng cổng được cấp ở mức cao bởi nguồn- TRUNG TÂM ADVANCECAD 18 cachdung.com - ungdungmaytinh.com
  • 17. UNGDUNGMAYTINH.COM dòng 100 μA trong PCF8574). Khi nhấn nút, P7 sẽ được nối với đất, làm cho đầu ra đọc bit-0. Ngắt EXTI Dự án RTC2 sử dụng ngắt EXTI để đạt được một ngắt báo động riêng biệt. Một vài bước nữa là cần thiết để đạt được ngắt trên PC14 cho ngắt/INT. Hãy xem phần mềm liên quan. Phần mềm dự án cho chương này được tìm thấy trong danh mục: $ cd ~/stm32f103c8t6/rtos/i2c-pcf8574 Ban đầu, chúng ta sẽ kiểm tra thiết lập I2C và EXTI trong chương trình main() của main.c (Bản kê 11-1). Bản kê 11-1. Thiết lập Ban đầu của các Ngắt I2C Ngoại vi và EXTI 0197: int 0198: main(void) { 0199: 0200: rcc_clock_setup_in_hse_8mhz_out_72mhz();// For "blue pill" 0201: rcc_periph_clock_enable(RCC_GPIOB); // I2C 0202: rcc_periph_clock_enable(RCC_GPIOC); // LED 0203: rcc_periph_clock_enable(RCC_AFIO); // EXTI 0204: rcc_periph_clock_enable(RCC_I2C1); // I2C 0205: 0206: gpio_set_mode(GPIOB, 0207: GPIO_MODE_OUTPUT_50_MHZ, 0208: GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, 0209: GPIO6|GPIO7); // I2C 0210: gpio_set(GPIOB,GPIO6|GPIO7); // Idle high 0211: 0212: gpio_set_mode(GPIOC, 0213: GPIO_MODE_OUTPUT_2_MHZ, 0214: GPIO_CNF_OUTPUT_PUSHPULL, 0215: GPIO13); // LED on PC13 0216: gpio_set(GPIOC,GPIO13); // PC13 LED dark 0217: 0218: // AFIO_MAPR_I2C1_REMAP=0, PB6+PB7 0219: gpio_primary_remap(0,0); 0220: 0221: gpio_set_mode(GPIOC, // PCF8574 /INT 0222: GPIO_MODE_INPUT, // Input 0223: GPIO_CNF_INPUT_FLOAT, 0224: GPIO14); // on PC14 0225: 0226: exti_select_source(EXTI14,GPIOC); 0227: exti_set_trigger(EXTI14,EXTI_TRIGGER_FALLING); 0228: exti_enable_request(EXTI14); 0229: nvic_enable_irq(NVIC_EXTI15_10_IRQ); // PC14 <- /INT TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 19
  • 18. Các dòng từ 201 đến 204 cho phép các xung của GPIOB (cho I2C), GPIOC (cho INT đọc LED và PC14), EXTI và thiết bị ngoại vi I2C. Dòng 206 cấu hình GPIO PB6 và PB7 cho hoạt động mở cống cho thiết bị ngoại vi I2C. Dòng 210 có thể không hoàn toàn cần thiết, nhưng cho đến khi thiết bị ngoại vi I2C được cấu hình, các đường bus I2C nên được đặt ở mức cao. Dòng 219 cấu hình I2C1 để sử dụng PB6 và PB7. Hàm libopencm3 gpio_primary_remap() có thể được sử dụng để thực hiện các lựa chọn khác. PB6 và PB7 hữu ích hơn vì chúng có nguồn đầu vào 5 V. Dòng 221 thiết lập GPIO PC14 làm đầu vào ở chế độ nổi. Đường này sẽ được R3 nối ở mức cao trong Hình 11-9. Dòng 226 đến 229 cấu hình ngắt EXTI. Hàm exti_select_source() chọn GPIO PC14 để thêm vào danh sách các nguồn ngắt. Dòng 227 sau đó cấu hình rằng ngắt sẽ xảy ra khi tín hiệu giảm từ cao xuống thấp. Cuối cùng, dòng 228 cho phép thiết bị ngoại vi EXTI yêu cầu ngắt. Các hàm gọi đến nvic_enable_irq() cho phép các vector ngắt NVIC_EXTI15_10_IRQ. Khi ngắt này xảy ra, đầu vào exti15_10_isr() sẽ được gọi. Để giúp bạn đỡ đau đầu phải tra cứu datasheet (RM0008) từ hãng ST Microelectronics, Bảng 11-2 được cung cấp. Theo ý kiến của tôi, datasheet không rõ ràng về cách ngắt cho EXTI được hỗ trợ. Bảng này cho thấy các dòng từ 0 đến 4 có vectơ ngắt riêng của chúng. Nhưng đối với các cổng GPIO đánh số từ 5 đến 9 hoặc từ 10 đến 15, các vectơ ngắt được chia sẻ rộng rãi hơn. Bảng 11-2. Danh sách Ngắt EXTI STM32F103 và Tên Chương trình ISR Ngắt Chương trình ISR Mô tả NVIC_EXTI0_IRQ exti0_isr() Dòng 0: PA0/PB0/PC0 NVIC_EXTI1_IRQ exti1_isr() Dòng 1: PA1/PB1/PC1 NVIC_EXTI2_IRQ exti2_isr() Dòng 2: PA2/PB2/PC2 NVIC_EXTI3_IRQ exti3_isr() Dòng 3: PA3/PB3/PC3 NVIC_EXTI4_IRQ exti4_isr() Dòng 4: PA4/PB4/PC4 NVIC_EXTI9_5_IRQ exti9_5_isr() Dòng 5 đến 9: PA5-9/PB5-9/PC5-9 NVIC_EXTI15_10_IRQ exti15_10_isr() Dòng 10 đến 15: PA10-15/PB10-15/PC10-15 NVIC_PVD_IRQ pvd_isr() Dòng 16: Power TRUNG TÂM ADVANCECAD 20 cachdung.com - ungdungmaytinh.com
  • 19. UNGDUNGMAYTINH.COM Ngắt Chương trình ISR Mô tả NVIC_RTC_ALARM_IRQ rtc_alarm_isr() Dòng 17: RTC Alarm NVIC_USB_WAKEUP_IRQ usb_wakeup_isr() Dòng 18: USB Wakeup Phần mềm I2C Mã nguồn để điều khiển thiết bị ngoại vi I2C đã được đặt trong mô đun nguồn i2c.c. Hàm quan tâm đầu tiên là i2c_configure(), được minh họa trong Bản kê 11-2. Bản kê 11-2. Cấu hình I2C 0061: void 0062: i2c_configure(I2C_Control *dev,uint32_t i2c,uint32_t ticks) { 0063: 0064: dev->device = i2c; 0065: dev->timeout = ticks; 0066: 0067: i2c_peripheral_disable(dev->device); 0068: i2c_reset(dev->device); 0069: I2C_CR1(dev->device) &= ~I2C_CR1_STOP; // Clear stop 0070: i2c_set_standard_mode(dev->device); // 100 kHz mode 0071: i2c_set_clock_frequency(dev->device,I2C_CR2_FREQ_36MHZ); // APB Freq 0072: i2c_set_trise(dev->device,36); // 1000 ns 0073: i2c_set_dutycycle(dev->device,I2C_CCR_DUTY_DIV2); 0074: i2c_set_ccr(dev->device,180); // 100 kHz <= 180 * 1 /36M 0075: i2c_set_own_7bit_slave_address(dev->device,0x23); 0076: i2c_peripheral_enable(dev->device); 0077: } Cấu trúc có tên I2C_Control được truyền vào làm đối số đầu tiên để giữ cấu hình. Địa chỉ ngoại vi I2C được truyền trong đối số i2c, sẽ là I2C1 cho bản demo này. Đối số cuối cùng xác định thời gian chờ được sử dụng, tính theo nhịp (tick). Các giá trị này được giữ nguyên trong I2C_Control trong các dòng 64 và 65 để sử dụng sau này. Các dòng 67 đến 69 xóa và reset thiết bị ngoại vi I2C để nếu nó bị lỗi, nó có thể “không làm cản trở”. Một trong những nhược điểm của I2C là giao thức đôi khi có thể treo nếu có lỗi xảy ra trên bus. Các dòng 70 đến 76 cấu hình thiết bị ngoại vi I2C và kích hoạt nó. Dòng 75 chỉ cần thiết nếu bạn muốn vận hành bộ điều khiển ở chế độ Slave. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 21
  • 20. Kiểm tra I2C Sẵn sàng Trước khi bất kỳ hoạt động I2C nào có thể được khởi tạo, bạn phải kiểm tra xem thiết bị có đang được sử dụng không. Nếu không, yêu cầu của bạn có thể bị bỏ qua hoặc sẽ gây lỗi cho hoạt động hiện tại. Bản kê 11-3 cho thấy chương trình được sử dụng. Bản kê 11-3. Kiểm tra I2C Sẵn sàng 0083: void 0084: i2c_wait_busy(I2C_Control *dev) { 0085: 0086: while ( I2C_SR2(dev->device) & I2C_SR2_BUSY ) 0087: taskYIELD(); // I2C Busy 0088: 0089: } Chương trình này sử dụng chương trình libopencm3 và macro để quản lý các thiết bị ngoại vi. Tuy nhiên, nếu thiết bị đang được sử dụng, điều khiển được chuyển đến các tác vụ FreeRTOS khác bằng cách sử dụng câu lệnh taskYIELD(). Bắt đầu I2C Để bắt đầu một giao tác bus I2C, thiết bị ngoại vi phải thực hiện thao tác “khởi động”. Điều này có thể liên quan đến xử lý bus nếu có nhiều Master đang được sử dụng. Bản kê 11-4 cho thấy chương trình được sử dụng trong bản demo. Bản kê 11-4. Hàm khởi động I2C 0095: void 0096: i2c_start_addr(I2C_Control *dev,uint8_t addr,enum I2C_RW rw) { 0097: TickType_t t0 = systicks(); 0098: 0099: i2c_wait_busy(dev); // Block until not busy 0100: I2C_SR1(dev->device) &= ~I2C_SR1_AF; // Clear Acknowledge failure 0101: i2c_clear_stop(dev->device); // Do not generate a Stop 0102: if ( rw == Read ) 0103: i2c_enable_ack(dev->device); 0104: i2c_send_start(dev->device); // Generate a Start/Restart 0105: 0106: // Loop until ready: 0107: while ( !((I2C_SR1(dev->device) & I2C_SR1_SB) 0108: && (I2C_SR2(dev->device) & (I2C_SR2_MSL|I2C_SR2_BUSY))) ) { 0109: if ( diff_ticks(t0,systicks()) > dev->timeout ) 0110: longjmp(i2c_exception,I2C_Addr_Timeout); 0111: taskYIELD(); 0112: } 0113: 0114: // Send Address & R/W flag: TRUNG TÂM ADVANCECAD 22 cachdung.com - ungdungmaytinh.com
  • 21. UNGDUNGMAYTINH.COM 0115: i2c_send_7bit_address(dev->device,addr, 0116: rw == Read ? I2C_READ : I2C_WRITE); 0117: 0118: // Wait until completion, NAK, or timeout 0119: t0 = systicks(); 0120: while ( !(I2C_SR1(dev->device) & I2C_SR1_ADDR) ) { 0121: if ( I2C_SR1(dev->device) & I2C_SR1_AF ) { 0122: i2c_send_stop(dev->device); 0123: (void)I2C_SR1(dev->device); 0124: (void)I2C_SR2(dev->device); // Clear flags 0125: // NAK Received (no ADDR flag will be set here) 0126: longjmp(i2c_exception,I2C_Addr_NAK); 0127: } 0128: if ( diff_ticks(t0,systicks()) > dev->timeout ) 0129: longjmp(i2c_exception,I2C_Addr_Timeout); 0130: taskYIELD(); 0131: } 0132: 0133: (void)I2C_SR2(dev->device); // Clear flags 0134: } Bước đầu tiên là để xác định nhịp thời gian (tick time) hiện tại trong dòng 97. Điều này cho phép chúng ta định thời cho thao tác và thời gian hết nếu cần thiết. Dòng 99 đợi cho thiết bị ngoại vi sẵn sàng. Khi đã sẵn sàng, dòng 100 xóa lỗi báo nhận, nếu có. Dòng 101 chỉ ra rằng không có điểm dừng nào được tạo ra. Nếu hoạt động là đọc, hàm i2c_enable_ack() được gọi để cho phép nhận ACK từ Slave. Thiết bị ngoại vi sau đó được yêu cầu tạo bit bắt đầu trong dòng 104. Các dòng 107 và 108 kiểm tra nếu bit bắt đầu đã được tạo ra. Nếu nó chưa được tạo ra, dòng 109 và 110 kiểm tra và thực hiện một longjmp() nếu hoạt động đã hết thời gian chờ. Chúng ta sẽ nói thêm về longjmp() hoạt động như một ngoại lệ sau này. Nếu không được hẹn giờ, câu lệnh FreeRTOS taskYIELD() được thực hiện để chia sẻ CPU trong khi chúng ta đợi. Khi bit bắt đầu đã được tạo, việc thực hiện tiếp tục ở dòng 115 để gửi địa chỉ Slave và báo đọc/ghi. Trong dòng 119 chúng ta lưu ý một lần nữa thời gian chờ khác. Dòng 120 đợi địa chỉ I2C được gửi đi, trong khi dòng 121 kiểm tra thiết bị Slave có báo nhận yêu cầu. Nếu không có thiết bị nào đáp ứng với địa chỉ được yêu cầu, một NAK sẽ được nhận theo mặc định (nhờ điện trở kéo lên). Nếu hoạt động hết thời gian, một longjmp() được thực hiện tại dòng 129. Nếu hoạt động thành công, cờ sẽ bị xóa bằng cách gọi I2C_SR2() để đọc thanh ghi trạng thái. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 23
  • 22. Ghi I2C Khi bit bắt đầu đã được tạo và địa chỉ được gửi, nếu chúng ta chỉ ra rằng ghi sau, chúng ta phải làm điều đó tiếp theo. Bản kê 11-5 cho thấy hàm ghi được sử dụng. Bản kê 11-5. Hàm Ghi I2C 0140: void 0141: i2c_write(I2C_Control *dev,uint8_t byte) { 0142: TickType_t t0 = systicks(); 0143: 0144: i2c_send_data(dev->device,byte); 0145: while ( !(I2C_SR1(dev->device) & (I2C_SR1_BTF)) ) { 0146: if ( diff_ticks(t0,systicks()) > dev->timeout ) 0147: longjmp(i2c_exception,I2C_Write_Timeout); 0148: taskYIELD(); 0149: } 0150: } Dòng 142 ghi lại thời gian cho thời gian chờ có thể xảy ra. Dòng 144 gửi byte dữ liệu đến thiết bị ngoại vi I2C để được gửi tuần tự trên bus. Dòng 145 kiểm tra để hoàn thành hoạt động này và hết thời gian với một longjmp() nếu cần thiết (dòng 147). Ngoài việc chia sẻ CPU với taskYIELD(), hàm trả về khi thành công. Đọc I2C Nếu ý định là đọc, chương trình đọc được sử dụng để đọc một byte dữ liệu. Bản kê 11-6 minh họa code được sử dụng. Bản kê 11-6. Hàm Đọc I2C 0157: uint8_t 0158: i2c_read(I2C_Control *dev,bool lastf) { 0159: TickType_t t0 = systicks(); 0160: 0161: if ( lastf ) 0162: i2c_disable_ack(dev->device); // Reading last/only byte 0163: 0164: while ( !(I2C_SR1(dev->device) & I2C_SR1_RxNE) ) { 0165: if ( diff_ticks(t0,systicks()) > dev->timeout ) 0166: longjmp(i2c_exception,I2C_Read_Timeout); 0167: taskYIELD(); 0168: } 0169: 0170: return i2c_get_data(dev->device); 0171: } Một trong những khía cạnh khác thường của hàm i2c_read() được trình bày là nó có một cờ Boolean lastf. Điều này được đặt là true bởi hàm gọi nếu nó là byte cuối TRUNG TÂM ADVANCECAD 24 cachdung.com - ungdungmaytinh.com
  • 23. UNGDUNGMAYTINH.COM cùng hoặc duy nhất được đọc. Điều này cung cấp cho các thiết bị Slave một đầu vào rằng nó có thể giảm (một số Slave phải tìm nạp trước dữ liệu để ở lại bước với bộ điều khiển Master). Đây là mục đích của hàm gọi trên dòng 162. Nếu không, đó là vấn đề kiểm tra trạng thái trong dòng 164 và hết thời gian trong dòng 166 nếu hoạt động mất quá nhiều thời gian. Nếu không, CPU được chia sẻ với taskYIELD() và byte được trả về trong dòng 170. Khởi động lại I2C Chương trình i2c_write_restart() được hiển thị một phần trong Bản kê 11-7 cung cấp khả năng thay đổi từ một yêu cầu ghi vào yêu cầu khác (đọc hoặc viết) mà không dừng lại. Bạn có thể tiếp tục với cùng một thiết bị Slave (bằng cách lặp lại cùng địa chỉ Slave) hoặc chuyển sang một thiết bị khác. Điều này là quan trọng khi có nhiều Master I2C vì điều này cho phép một tin nhắn khác mà không thông qua quyền truy cập vào bus. Bản kê 11-7. “Bí quyết” để Thực hiện một Giao tác I2C Restart void 0179: i2c_write_restart(I2C_Control *dev,uint8_t byte,uint8_t addr) { 0180: TickType_t t0 = systicks(); 0181: 0182: taskENTER_CRITICAL(); 0183: i2c_send_data(dev->device,byte); 0184: // Must set start before byte has written out 0185: i2c_send_start(dev->device); 0186: taskEXIT_CRITICAL(); Một số loại thông tin khó có thể rút ra từ Tài liệu STM32 (RM0008). Tuy nhiên, chú ý cẩn thận đến bản xuất và chú thích nhỏ đôi khi có thể mang lại giá trị lớn. Hướng dẫn sử dụng cho biết: Trong chế độ Master, thiết lập bit START khiến giao thức tạo ra một điều kiện khởi động lại ở cuối đợt chuyển byte hiện thời. Bằng cách tạo dòng 182 đến 186 một phần quan trọng, bạn đảm bảo rằng bạn yêu cầu một “bắt đầu” khác trước khi ghi I2C hiện tại đang được hoàn thành. Chương trình demo Bản kê 11-8 minh họa vòng lặp chính của chương trình demo. Hầu hết nó đơn giản, nhưng có một vài điều đáng chú ý. Sau khi thiết bị I2C được cấu hình trong dòng 131, vòng lặp bên trong bắt đầu tại dòng 134. Miễn là không có đầu vào bàn phím, vòng lặp này tiếp tục ghi và đọc từ chip PCF8574. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 25
  • 24. Bản kê 11-8. Vòng lặp chính của Chương trình demo 0116: static void 0117: task1(void *args __attribute__((unused))) { 0118: uint8_t addr = PCF8574_ADDR(0); // I2C Address 0119: volatile unsigned line = 0u; // Print line # 0120: volatile uint16_t value = 0u; // PCF8574P value 0121: uint8_t byte = 0xFF; // Read I2C byte 0122: volatile bool read_flag; // True if Interrupted 0123: I2C_Fails fc; // I2C fail code 0124: 0125: for (;;) { 0126: wait_start(); 0127: usb_puts("nI2C Demo Begins " 0128: "(Press any key to stop)nn"); 0129: 0130: // Configure I2C1 0131: i2c_configure(&i2c,I2C1,1000); 0132: 0133: // Until a key is pressed: 0134: while ( usb_peek() <= 0 ) { 0135: if ( (fc = setjmp(i2c_exception)) != I2C_Ok ) { 0136: // I2C Exception occurred: 0137: usb_printf("I2C Fail code %dnn", fc,i2c_error(fc)); 0138: break; 0139: } 0140: 0141: read_flag = wait_event(); // Interrupt or timeout 0142: 0143: // Left four bits for input, are set to 1-bits 0144: // Right four bits for output: 0145: 0146: value = (value & 0x0F) | 0xF0; 0147: usb_printf("Writing $%02X " "I2C @ $%02Xn",value,addr); 0148: #if 0 0149: /********************************************* 0150: * This example performs a write transaction, 0151: * followed by a separate read transaction: 0152: *********************************************/ 0153: i2c_start_addr(&i2c,addr,Write); 0154: i2c_write(&i2c,value&0x0FF); 0155: i2c_stop(&i2c); 0156: 0157: i2c_start_addr(&i2c,addr,Read); 0158: byte = i2c_read(&i2c,true); 0159: i2c_stop(&i2c); 0160: #else 0161: /********************************************* 0162: * This example performs a write followed TRUNG TÂM ADVANCECAD 26 cachdung.com - ungdungmaytinh.com
  • 25. UNGDUNGMAYTINH.COM 0163: * immediately by a read in one I2C transaction, 0164: * using a "Repeated Start" 0165: *********************************************/ 0166: i2c_start_addr(&i2c,addr,Write); 0167: i2c_write_restart(&i2c,value&0x0FF,addr); 0168: byte = i2c_read(&i2c,true); 0169: i2c_stop(&i2c); 0170: #endif 0171: if ( read_flag ) { 0172: // Received an ISR interrupt: 0173: if ( byte & 0b10000000 ) 0174: usb_printf("%04u: BUTTON RELEASED: " 0175: "$%02X; wrote $%02X, " "ISR %dn", 0176: ++line,byte, value,isr_count); 0177: else usb_printf("%04u: BUTTON PRESSED: " 0178: "$%02X; wrote $%02X, " "ISR %dn", 0179: ++line,byte, value,isr_count); 0180: } else { 0181: // No interrupt(s): 0182: usb_printf("%04u: " "Read: $%02X, " 0183: "wrote $%02X, ISR %dn", 0184: ++line,byte,value,isr_count); 0185: } 0186: value = (value + 1) & 0x0F; 0187: } 0188: 0189: usb_printf("nPress any key to restart.n"); 0190: } 0191: } Lưu ý đặc biệt là setjmp() tại dòng 135. Vì C thiếu cơ chế ngoại lệ mà C++ sở hữu, nên longjmp() được sử dụng thay thế. Việc thực hiện setjmp() của chúng ta ở đầu vòng lặp cho phép chúng ta thực hiện một số hàm gọi I2C sau đó, mỗi hàm gọi có điểm thất bại riêng, bao gồm cả thời gian chờ. Nếu bất kỳ lỗi nào xảy ra, longjmp() sẽ đưa điều khiển trở lại dòng 135 và trả về code lỗi khác 0. Từ đó vấn đề có thể được báo cáo và thoát ra khỏi vòng lặp bên trong. Cơ chế setjmp/longjmp cũng có chút yêu cầu cần lưu ý. Chú ý rằng các biến line, value và read_flag được đánh dấu dễ thay đổi (các dòng 119 đến 122). Điều này là cần thiết để làm trình biên dịch ổn định vì nó cảnh báo về các giá trị đó đang được thay đổi do kết quả của longjmp(), nếu nó xảy ra. setjmp tiết kiệm một loạt các thanh ghi, trong khi longjmp phục hồi chúng để mang điều khiển trở lại. Bất kỳ biến nào cũng được lưu trong bộ nhớ đệm sẽ bị ghi đè bởi longjmp. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 27
  • 26. Có các câu lệnh #if, #else và #endif trong dòng 148, 160 và 170 tương ứng. Bằng cách thay đổi dòng 148 từ giá trị 0 thành giá trị khác 0, tất cả các giao tác sẽ là đơn lẻ; tức là, byte sẽ được ghi ra PCF8574P trong một giao tác, tiếp theo là một giao tác I2C hoàn toàn riêng biệt để đọc từ nó. Để dòng 148 ở giá trị 0 cho phép bạn kiểm tra hoạt động khởi động lại I2C. Các dòng từ 166 đến 169 thực hiện một lệnh viết tiếp theo là đọc trong cùng một giao tác. Phiên Demo Thực hiện build từ đầu như sau: $ make clobber $ make arm-none-eabi-gcc ... -o main.elf arm-none-eabi-size main.elf text data bss dec hex filename 13024 28 18200 31252 7a14 main.elf Sẵn sàng cho thiết bị nạp flash và thực hiện các thao tác sau: $ make flash arm-none-eabi-objcopy -Obinary main.elf main.bin /usr/local/bin/st-flash write main.bin 0x8000000 ... 2017-12-09T21:32:12 INFO src/common.c: Flash written and verified! jolly good! Bây giờ, cắm cáp USB vào và khởi động minicom, như sau: $ minicom usb Welcome to minicom 2.7 OPTIONS: Compiled on Sep 17 2016, 05:53:15. Port /dev/cu.usbmodemWGDEM1, 21:33:40 Press Meta-Z for help on special keys Task1 begun. Press any key to begin. Một lần nữa, đối số “usb” cho minicom là tên của file mà bạn đã lưu cài đặt minicom của mình. Tôi đã sử dụng file có tên là usb trong ví dụ này. Khi bạn thấy “Task1 begun”, hãy nhấn phím bất kỳ. Tôi nhấn Return (Enter). Khi bạn làm điều đó, thiết bị I2C sẽ được cấu hình và bạn sẽ bắt đầu thấy các thông báo có dạng sau: I2C Demo Begins (Press any key to stop) Writing $F0 I2C @ $20 TRUNG TÂM ADVANCECAD 28 cachdung.com - ungdungmaytinh.com
  • 27. UNGDUNGMAYTINH.COM 0001: Read: $F0, wrote $F0, ISR 0 Writing $F1 I2C @ $20 0002: Read: $F1, wrote $F1, ISR 0 Nếu bạn nhấn phím một lần nữa, điều khiển sẽ dừng lại và sau đó thoát ra vòng lặp ngoài. Nhấn phím một lần nữa sẽ khởi động lại bản demo ở vòng lặp trong. Các giá trị được ghi ra cho PCF8574P sẽ tăng trong bốn bit thấp hơn. Nếu bạn gắn LED vào P0 và P1 như trong sơ đồ, bạn sẽ thấy chúng được đếm ngược dưới dạng nhị phân. Khi bạn nhấn nút, bạn sẽ thấy một số thông báo cho biết nút bấm và giải phóng event. Writing $F5 I2C @ $20 0006: Read: $F5, wrote $F5, ISR 0 Writing $F6 I2C @ $20 0007: Read: $F6, wrote $F6, ISR 0 Writing $F7 I2C @ $20 0008: BUTTON PRESSED: $77; wrote $F7, ISR 4 Writing $F8 I2C @ $20 0009: BUTTON PRESSED: $78; wrote $F8, ISR 4 Writing $F9 I2C @ $20 0010: BUTTON PRESSED: $79; wrote $F9, ISR 5 Writing $FA I2C @ $20 0011: BUTTON PRESSED: $7A; wrote $FA, ISR 6 Writing $FB I2C @ $20 0012: BUTTON PRESSED: $7B; wrote $FB, ISR 7 Writing $FC I2C @ $20 0013: BUTTON PRESSED: $7C; wrote $FC, ISR 8 Writing $FD I2C @ $20 0014: Read: $7D, wrote $FD, ISR 8 Writing $FE I2C @ $20 0015: BUTTON RELEASED: $FE; wrote $FE, ISR 11 Giá trị được hiển thị sau ISR cho bạn biết số lần chương trình ISR được gọi khi PCF8574P chỉ báo ngắt. Nút của tôi khá là cũ, nó không nhả tốt, nên bạn thấy một số event bấm nút. Lưu ý rằng trong khi nút được giữ lại, bit trên thay đổi từ bit-1 thành bit-0 (ví dụ, $FX thay đổi thành $7X). Tóm tắt Chương này giúp bạn chuẩn bị tốt cho công việc I2C. PCF8574 là một giải pháp rất tiết kiệm để bổ sung thêm các cổng GPIO miễn là bạn không yêu cầu tốc độ cao. Đồng thời, nó cung cấp cho bạn kinh nghiệm trong thế giới I2C. PCF8574 đã chứng minh rằng nó có thể tạo ra các ngắt để bạn không phải liên tục kiểm tra các thay đổi đường đầu vào. Điều này giúp giảm bớt gánh nặng của lưu lượng I2C trên bus. TRUNG TÂM ADVANCECAD cachdung.com - ungdungmaytinh.com 29