diff --git a/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANBus.cs b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANBus.cs new file mode 100644 index 0000000..789f76b --- /dev/null +++ b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANBus.cs @@ -0,0 +1,37 @@ +using BusCommPracticeConsoleApp.Models; + +namespace BusCommPracticeConsoleApp.CANs +{ + public class CANBus + { + private readonly List _nodes = new List(); + private CanFrame _currentFrame = null; + + public void AddNode(CANNode node) + { + _nodes.Add(node); + node.ConnectToBus(this); + } + + public void SendFrame(CANNode sender, CanFrame frame) + { + if (_currentFrame != null && frame.ID >= _currentFrame.ID) + { + Console.WriteLine("Already higher priority frame is used."); + return; + } + + _currentFrame = frame; + Console.WriteLine($"{sender.Name} node send the frame{Environment.NewLine}{frame}"); + } + + public void CompleteTransmission() + { + if (_currentFrame == null) + return; + + Console.WriteLine($"Send 0x{_currentFrame.ID.ToString("X8")} frame complete."); + _currentFrame = null; + } + } +} \ No newline at end of file diff --git a/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANNode.cs b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANNode.cs new file mode 100644 index 0000000..6378ee9 --- /dev/null +++ b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CANNode.cs @@ -0,0 +1,35 @@ +namespace BusCommPracticeConsoleApp.CANs +{ + public class CANNode + { + public string Name { get; set; } + private CANBus _bus; + + public CANNode(string name) + { + Name = name; + } + + public void ConnectToBus(CANBus bus) + { + _bus = bus; + } + + public void SendMessage(uint id, byte[] data) + { + var frame = new CanFrame(id, false, data); + _bus.SendFrame(this, frame); + } + + public void ReceiveFrame(CanFrame frame) + { + if (frame.CRC != frame.CRC) + Console.WriteLine("<{Name}> node CRC check error!"); + } + + public void AcknowledgeFrame() + { + Console.WriteLine($"<{Name}> node acknowledged."); + } + } +} \ No newline at end of file diff --git a/BusCommPractice/BusCommPracticeConsoleApp/CANs/CanFrame.cs b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CanFrame.cs new file mode 100644 index 0000000..4f20c1c --- /dev/null +++ b/BusCommPractice/BusCommPracticeConsoleApp/CANs/CanFrame.cs @@ -0,0 +1,65 @@ +using System.Text; + +namespace BusCommPracticeConsoleApp.CANs +{ + public class CanFrame + { + // Field Define + public bool SOF { get; set; } = true; // Start of Frame (1bit) + public uint ID { get; set; } // Identifier (29bits) + public bool RTR { get; set; } // Remote Transmittion Request (1bit) + public byte DLC { get; set; } // Data Length Code (4bit, 0~8) + public byte[] Data { get; set; } // Data Field (0~8 bytes) + public ushort CRC { get; set; } // Cyclic Redundancy Check (15bits) + public bool ACK { get; set; } // Acknowledge (1bit) + public byte EOF { get; set; } // End of Frame (7bits, all 1) + + public CanFrame(uint id, bool rtr, byte[] data) + { + if (id > 0x1FFFFFFF) // 29bits check + throw new ArgumentException("The id cannot larger than 29bits."); + + if (data.Length > 8) + throw new ArgumentException("The data length cannot larger than 8bytes."); + + ID = id; + RTR = rtr; + DLC = (byte)data.Length; + Data = data; + CRC = CalculateCRC(); + ACK = false; + } + + private ushort CalculateCRC() + { + uint crc = ID; + crc += RTR ? 1u : 0u; + crc += DLC; + foreach (var c in Data) + crc += c; + + return (ushort)(crc & 0x7FFF); // 15bits masking + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("=== CAN 2.0B Frame ==="); + sb.AppendLine($"SOF: {SOF}"); + sb.AppendLine($"ID: 0x{ID:X8}"); + sb.AppendLine($"RTR: {RTR}"); + sb.AppendLine($"DLC: {DLC}"); + sb.Append("Data: "); + for (int i = 0; i < DLC; i++) + { + sb.Append($"0x{Data[i]:X2} "); + } + sb.AppendLine(); + sb.AppendLine($"CRC: 0x{CRC:X4}"); + sb.AppendLine($"ACK: {ACK}"); + sb.AppendLine($"EOF: 0b{Convert.ToString(EOF, 2).PadLeft(7, '0')}"); + sb.AppendLine("======================"); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/BusCommPractice/BusCommPracticeConsoleApp/Program.cs b/BusCommPractice/BusCommPracticeConsoleApp/Program.cs index c30bf2d..983188a 100644 --- a/BusCommPractice/BusCommPracticeConsoleApp/Program.cs +++ b/BusCommPractice/BusCommPracticeConsoleApp/Program.cs @@ -1,4 +1,6 @@ -using BusCommPracticeConsoleApp.Models; +using System.Text; +using BusCommPracticeConsoleApp.CANs; +using BusCommPracticeConsoleApp.Models; namespace BusCommPracticeConsoleApp; @@ -6,21 +8,48 @@ class Program { static void Main(string[] args) { - IMessageBus messageBus1= new MessageBus(); - IMessageBus messageBus2= new MessageBus(); + /********************** + MESSAGE BUS + **********************/ - var subscriber1 = new Subscriber(messageBus1, "Sub1"); - var subscriber2 = new Subscriber(messageBus1, "Sub2"); - var subscriber3 = new Subscriber(messageBus2, "Sub3"); + // IMessageBus messageBus1= new MessageBus(); + // IMessageBus messageBus2= new MessageBus(); - var publisher1 = new Publisher(messageBus1); - var publisher2 = new Publisher(messageBus2); + // var subscriber1 = new Subscriber(messageBus1, "Sub1"); + // var subscriber2 = new Subscriber(messageBus1, "Sub2"); + // var subscriber3 = new Subscriber(messageBus2, "Sub3"); - publisher1.SendMessage("Hello, Bus!"); - publisher1.SendMessage("I'm publisher 1"); + // var publisher1 = new Publisher(messageBus1); + // var publisher2 = new Publisher(messageBus2); - publisher2.SendMessage("Hello, Bus!"); - publisher2.SendMessage("I'm publisher 2"); + // publisher1.SendMessage("Hello, Bus!"); + // publisher1.SendMessage("I'm publisher 1"); + + // publisher2.SendMessage("Hello, Bus!"); + // publisher2.SendMessage("I'm publisher 2"); + + + /********************** + CAN BUS + **********************/ + var bus = new CANBus(); + + var nodeA = new CANNode("NodeA"); + var nodeB = new CANNode("NodeB"); + var nodeC = new CANNode("NodeC"); + + bus.AddNode(nodeA); + bus.AddNode(nodeB); + bus.AddNode(nodeC); + + nodeA.SendMessage(0x1ABCDEFF, Encoding.UTF8.GetBytes("PHK")); + nodeB.SendMessage(0x0123F321, new byte[] { 0x55, 0x66, 0x77, 0x88 }); + + bus.CompleteTransmission(); + + Thread.Sleep(1000); + nodeC.SendMessage(0x12345678, new byte[] { 0x99, 0xAA, 0xBB, 0xCC }); + bus.CompleteTransmission(); Console.ReadLine(); }